Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
jedi
smrtlink
Commits
da8ac53f
Commit
da8ac53f
authored
Oct 15, 2015
by
/jdi/
Browse files
json lib added
parent
ff585313
Changes
20
Hide whitespace changes
Inline
Side-by-side
src/Host.cpp
View file @
da8ac53f
...
...
@@ -23,18 +23,20 @@
#include
"Options.h"
#include
"Host.h"
#include
"Types
/Types
.h"
#include
"Types.h"
macAddr
Host
::
getMac
()
{
int
s
;
struct
ifreq
buffer
;
int
s
;
struct
ifreq
buffer
;
macAddr
data
{
0
,
0
,
0
,
0
,
0
,
0
};
s
=
socket
(
PF_INET
,
SOCK_DGRAM
,
0
);
memset
(
&
buffer
,
0x00
,
sizeof
(
buffer
));
strcpy
(
buffer
.
ifr_name
,
options
.
interface
.
c_str
());
ioctl
(
s
,
SIOCGIFHWADDR
,
&
buffer
);
close
(
s
);
memcpy
(
&
data
[
0
],
&
buffer
.
ifr_hwaddr
.
sa_data
[
0
],
6
);
if
(
options
.
interface
!=
""
)
{
s
=
socket
(
PF_INET
,
SOCK_DGRAM
,
0
);
memset
(
&
buffer
,
0x00
,
sizeof
(
buffer
));
strcpy
(
buffer
.
ifr_name
,
options
.
interface
.
c_str
());
ioctl
(
s
,
SIOCGIFHWADDR
,
&
buffer
);
close
(
s
);
memcpy
(
&
data
[
0
],
&
buffer
.
ifr_hwaddr
.
sa_data
[
0
],
6
);
}
return
data
;
}
...
...
@@ -55,6 +57,15 @@ ipAddr Host::getIp() {
return
data
;
}
}
for
(
ifa
=
ifaddr
,
n
=
0
;
ifa
!=
NULL
;
ifa
=
ifa
->
ifa_next
,
n
++
)
{
if
(
ifa
->
ifa_addr
==
NULL
)
continue
;
if
(
ifa
->
ifa_addr
->
sa_family
==
AF_INET
)
if
(
getIface
().
compare
(
ifa
->
ifa_name
)
==
0
)
{
memcpy
(
&
data
[
0
],
&
ifa
->
ifa_addr
->
sa_data
[
2
],
4
);
return
data
;
}
}
freeifaddrs
(
ifaddr
);
return
data
;
}
...
...
src/Host.h
View file @
da8ac53f
...
...
@@ -8,7 +8,7 @@
#ifndef HOST_H_
#define HOST_H_
#include
"Types
/Types
.h"
#include
"Types.h"
class
Host
{
public:
...
...
src/Lookup.h
View file @
da8ac53f
...
...
@@ -5,7 +5,7 @@
* Author: jdi
*/
#include
"
Types/
lookupTable.h"
#include
"lookupTable.h"
static
lookupTable
rcv_lookup
=
{
{
1
,
"type"
},
//string
{
2
,
"hostname"
},
//string
...
...
src/Options.h
View file @
da8ac53f
...
...
@@ -8,26 +8,27 @@
#ifndef OPTIONS_H_
#define OPTIONS_H_
#include
"Types
/Types
.h"
#include
"Types.h"
#define VERSION "smrtlink (v1 Linux)\n"
#define USAGE "usage: %s [-bhrvx] [-i interface] [-u [password:]username]\n\
#define USAGE "usage: %s [-b
d
hrv
sw
x] [-i interface] [-u [password:]username]\n\
[-p password] <command>\n\n"
#define HELP "\
### for questions please contact <smrtlink@jdi.li> ###\n\
Option Summary:\n\
-h --help This help text\n\
-v --version Display version of this tool\n\
-r switch ports to emulate switch while sniffing\n\
-b --header Show header\n\
-x --hex Display Packets as Hex String\n\
-i --interface only use one Interface\n\
-u --user Login with user\n\
-p Password\n\
-f --file Not yet implemented:.choose a settings file\n\
-t --timeout Not yet implemented\n\
-w --wait Not yet implemented: blocking until operation is completed\n\
-s --permanent Not yet implemented: make changes immediately permanent\n\n\
-h --help This help text\n\
-v --version Display version of this tool\n\
-d --debug [n] Show debugging messages\n\
-r switch ports to emulate switch while sniffing\n\
-b --header Show header\n\
-x --hex Display Packets as Hex String\n\
-i --interface <iface> only use one Interface\n\
-u --user <[password:]username>\n\
-p --password <password>\n\
Login with Username and Password\n\
-f --file <path> Not yet implemented:.choose a settings file\n\
-t --timeout <n> Not yet implemented\n\
-w --wait Not yet implemented: blocking until operation is completed\n\
-s --permanent Not yet implemented: make changes immediately permanent\n\n\
Command Summary:\n\
help This help text\n\
list list all connected switches\n\
...
...
@@ -40,13 +41,15 @@
restore Not yet implemented: restore onfig from file\n\
flash Not yet implemented: replace firmware\n\
reboot Not yet implemented\n\
reset Not yet implemented\n\n"
reset Not yet implemented\n\n\
### for questions please contact <smrtlink@jdi.li> ###\n\n"
#define FLAG_HEX 1
#define FLAG_REVERSE 2
#define FLAG_HEADER 4
#define FLAG_PERMANENT 8
#define FLAG_WAIT 16
#define FLAG_DEBUG 32
extern
Options
options
;
...
...
src/Packet.cpp
View file @
da8ac53f
...
...
@@ -9,7 +9,7 @@
#include
<cstdlib>
#include
<ctime>
#include
"Packet.h"
#include
"Types
/Types
.h"
#include
"Types.h"
Packet
::
Packet
(
OpCode
c
)
{
srand
(
time
(
NULL
));
...
...
src/Packet.h
View file @
da8ac53f
...
...
@@ -11,7 +11,7 @@
#define HEADER_LEN 32
#define PACKET_END 0xFFFF0000
#include
"Types
/Types
.h"
#include
"Types.h"
class
Packet
{
public:
...
...
src/Program.cpp
View file @
da8ac53f
...
...
@@ -17,7 +17,7 @@
int
Program
::
list
()
{
printf
(
"List:
\n
"
)
;
std
::
cout
<<
"List:
\n
"
;
Packet
p
=
Packet
(
Packet
::
DISCOVERY
);
p
.
setHostMac
(
host
.
getMac
());
p
.
setPayload
(
{
});
...
...
@@ -162,12 +162,21 @@ int Program::getProperty() {
return
1
;
}
int
Program
::
save
()
{
Switch
sw
=
Switch
();
std
::
string
str
=
sw
.
toString
();
//File = fopen(otions.file)
return
0
;
}
int
Program
::
restore
()
{
const
char
str
[]
=
" {
\"
hello
\"
:
\"
world
\"
,
\"
t
\"
: true ,
\"
f
\"
: false,
\"
n
\"
: null,
\"
i
\"
:123,
\"
pi
\"
: 3.1416,
\"
a
\"
:[1, 2, 3, 4] } "
;
printf
(
"Original JSON:
\n
%s
\n
"
,
str
);
Switch
sw
=
Switch
();
sw
.
parse
(
str
);
//File = fopen(otions.file)
return
0
;
return
1
;
}
int
Program
::
flash
()
{
...
...
@@ -182,6 +191,6 @@ int Program::reset() {
return
0
;
}
void
Program
::
init
()
{
if
(
options
.
interface
.
compare
(
""
)
==
0
)
if
(
options
.
interface
.
compare
(
""
)
==
0
)
options
.
interface
=
host
.
getIface
();
}
src/Program.h
View file @
da8ac53f
...
...
@@ -8,7 +8,7 @@
#ifndef PROGRAM_H_
#define PROGRAM_H_
#include
"Types
/Types
.h"
#include
"Types.h"
#include
"Host.h"
class
Program
{
...
...
src/Socket.cpp
View file @
da8ac53f
...
...
@@ -15,7 +15,7 @@
#include
"Packet.h"
#include
"Options.h"
#include
"Host.h"
#include
"Types
/Types
.h"
#include
"Types.h"
Socket
::
Socket
(
asio
::
io_service
&
io_service
)
:
send_socket_
(
io_service
),
receive_socket_
(
io_service
)
{
...
...
@@ -29,7 +29,8 @@ void Socket::init(short dst_port, short src_port) {
src_port
=
p
;
}
std
::
cout
<<
"IP:
\t
"
<<
local_ip
<<
"
\n
"
;
if
(
options
.
flags
&
FLAG_DEBUG
)
std
::
cout
<<
"Local IP:
\t
"
<<
local_ip
<<
"
\n
"
;
wildcard_endpoint_
=
asio
::
ip
::
udp
::
endpoint
(
asio
::
ip
::
address_v4
::
from_string
(
"0.0.0.0"
),
src_port
);
...
...
@@ -51,7 +52,7 @@ void Socket::init(short dst_port, short src_port) {
}
void
Socket
::
setHostIp
(
ipAddr
ip
)
{
local_ip
=
ip
;
local_ip
=
ip
;
}
void
Socket
::
send
(
bytes
data
)
{
...
...
src/Socket.h
View file @
da8ac53f
...
...
@@ -10,7 +10,7 @@
#include
<asio.hpp>
#include
"Packet.h"
#include
"Types
/Types
.h"
#include
"Types.h"
#define SRC_PORT 29809
#define DST_PORT 29808
...
...
src/Switch.cpp
View file @
da8ac53f
...
...
@@ -6,33 +6,212 @@
*/
#include
<string>
#include
"Types
/Types
.h"
#include
"Types.h"
#include
"Switch.h"
#include
"Lookup.h"
#include
"Options.h"
void
Switch
::
parse
(
datasets
arr
)
{
device
.
type
=
arr
[
1
].
value
;
settings
.
hostname
=
arr
[
2
].
value
;
device
.
mac
=
arr
[
3
].
value
;
settings
.
ip_addr
=
arr
[
4
].
value
;
settings
.
ip_mask
=
arr
[
5
].
value
;
settings
.
gateway
=
arr
[
6
].
value
;
device
.
firmware_version
=
arr
[
7
].
value
;
device
.
hardware_version
=
arr
[
8
].
value
;
settings
.
dhcp
=
arr
[
9
].
value
[
0
];
int
Switch
::
parse
(
datasets
arr
)
{
for
(
auto
a
:
arr
)
{
parse
(
a
.
second
);
}
return
0
;
}
void
Switch
::
parse
(
dataset
d
)
{
int
Switch
::
parse
(
dataset
d
)
{
auto
lookup
=
(
options
.
flags
&
FLAG_REVERSE
)
?
snd_lookup
:
rcv_lookup
;
if
(
d
.
type
==
lookup
[
"type"
]){
if
(
d
.
type
==
lookup
[
"type"
])
{
device
.
type
=
d
.
value
;
}
if
(
d
.
type
==
lookup
[
"mac"
]){
if
(
d
.
type
==
lookup
[
"mac"
])
{
device
.
mac
=
d
.
value
;
}
if
(
d
.
type
==
lookup
[
"type"
]){
device
.
type
=
d
.
value
;
if
(
d
.
type
==
lookup
[
"firmware_version"
])
{
device
.
firmware_version
=
d
.
value
;
}
if
(
d
.
type
==
lookup
[
"hardware_version"
])
{
device
.
hardware_version
=
d
.
value
;
}
if
(
d
.
type
==
lookup
[
"hostname"
])
{
settings
.
hostname
=
d
.
value
;
}
if
(
d
.
type
==
lookup
[
"ip_addr"
])
{
settings
.
ip_addr
=
d
.
value
;
}
if
(
d
.
type
==
lookup
[
"ip_mask"
])
{
settings
.
ip_mask
=
d
.
value
;
}
if
(
d
.
type
==
lookup
[
"gateway"
])
{
settings
.
gateway
=
d
.
value
;
}
if
(
d
.
type
==
lookup
[
"dhcp"
])
{
settings
.
dhcp
=
d
.
value
[
0
];
}
return
0
;
}
int
Switch
::
parse
(
std
::
string
str
)
{
if
(
json
.
Parse
(
str
.
c_str
()).
HasParseError
())
return
1
;
if
(
options
.
flags
&
FLAG_DEBUG
)
std
::
cout
<<
"
\n
Parsing to document succeeded.
\n
"
;
////////////////////////////////////////////////////////////////////////////
// 2. Access values in document.
printf
(
"
\n
Access values in document:
\n
"
);
assert
(
json
.
IsObject
());
// Document is a JSON value represents the root of DOM. Root can be either an object or array.
assert
(
json
.
HasMember
(
"hello"
));
assert
(
json
[
"hello"
].
IsString
());
printf
(
"hello = %s
\n
"
,
json
[
"hello"
].
GetString
());
// Since version 0.2, you can use single lookup to check the existing of member and its value:
rapidjson
::
Value
::
MemberIterator
hello
=
json
.
FindMember
(
"hello"
);
assert
(
hello
!=
json
.
MemberEnd
());
assert
(
hello
->
value
.
IsString
());
assert
(
strcmp
(
"world"
,
hello
->
value
.
GetString
())
==
0
);
(
void
)
hello
;
assert
(
json
[
"t"
].
IsBool
());
// JSON true/false are bool. Can also uses more specific function IsTrue().
printf
(
"t = %s
\n
"
,
json
[
"t"
].
GetBool
()
?
"true"
:
"false"
);
assert
(
json
[
"f"
].
IsBool
());
printf
(
"f = %s
\n
"
,
json
[
"f"
].
GetBool
()
?
"true"
:
"false"
);
printf
(
"n = %s
\n
"
,
json
[
"n"
].
IsNull
()
?
"null"
:
"?"
);
assert
(
json
[
"i"
].
IsNumber
());
// Number is a JSON type, but C++ needs more specific type.
assert
(
json
[
"i"
].
IsInt
());
// In this case, IsUint()/IsInt64()/IsUInt64() also return true.
printf
(
"i = %d
\n
"
,
json
[
"i"
].
GetInt
());
// Alternative (int)document["i"]
assert
(
json
[
"pi"
].
IsNumber
());
assert
(
json
[
"pi"
].
IsDouble
());
printf
(
"pi = %g
\n
"
,
json
[
"pi"
].
GetDouble
());
{
const
rapidjson
::
Value
&
a
=
json
[
"a"
];
// Using a reference for consecutive access is handy and faster.
assert
(
a
.
IsArray
());
for
(
rapidjson
::
SizeType
i
=
0
;
i
<
a
.
Size
();
i
++
)
// rapidjson uses SizeType instead of size_t.
printf
(
"a[%d] = %d
\n
"
,
i
,
a
[
i
].
GetInt
());
int
y
=
a
[
0
].
GetInt
();
(
void
)
y
;
// Iterating array with iterators
printf
(
"a = "
);
for
(
rapidjson
::
Value
::
ConstValueIterator
itr
=
a
.
Begin
();
itr
!=
a
.
End
();
++
itr
)
printf
(
"%d "
,
itr
->
GetInt
());
printf
(
"
\n
"
);
}
// Iterating object members
static
const
char
*
kTypeNames
[]
=
{
"Null"
,
"False"
,
"True"
,
"Object"
,
"Array"
,
"String"
,
"Number"
};
for
(
rapidjson
::
Value
::
ConstMemberIterator
itr
=
json
.
MemberBegin
();
itr
!=
json
.
MemberEnd
();
++
itr
)
printf
(
"Type of member %s is %s
\n
"
,
itr
->
name
.
GetString
(),
kTypeNames
[
itr
->
value
.
GetType
()]);
return
0
;
}
std
::
string
Switch
::
toString
()
{
////////////////////////////////////////////////////////////////////////////
// 3. Modify values in document.
// Change i to a bigger number
{
uint64_t
f20
=
1
;
// compute factorial of 20
for
(
uint64_t
j
=
1
;
j
<=
20
;
j
++
)
f20
*=
j
;
json
[
"i"
]
=
f20
;
// Alternate form: document["i"].SetUint64(f20)
assert
(
!
json
[
"i"
].
IsInt
());
// No longer can be cast as int or uint.
}
// Adding values to array.
{
rapidjson
::
Value
&
a
=
json
[
"a"
];
// This time we uses non-const reference.
rapidjson
::
Document
::
AllocatorType
&
allocator
=
json
.
GetAllocator
();
for
(
int
i
=
5
;
i
<=
10
;
i
++
)
a
.
PushBack
(
i
,
allocator
);
// May look a bit strange, allocator is needed for potentially realloc. We normally uses the document's.
// Fluent API
a
.
PushBack
(
"Lua"
,
allocator
).
PushBack
(
"Mio"
,
allocator
);
}
// Making string values.
// This version of SetString() just store the pointer to the string.
// So it is for literal and string that exists within value's life-cycle.
{
json
[
"hello"
]
=
"hostname"
;
//settings.hostname; // This will invoke strlen()
// Faster version:
// document["hello"].SetString("rapidjson", 9);
}
// This version of SetString() needs an allocator, which means it will allocate a new buffer and copy the the string into the buffer.
rapidjson
::
Value
author
;
{
char
buffer
[
10
];
int
len
=
sprintf
(
buffer
,
"%s %s"
,
"Milo"
,
"Yip"
);
// synthetic example of dynamically created string.
author
.
SetString
(
buffer
,
static_cast
<
size_t
>
(
len
),
json
.
GetAllocator
());
// Shorter but slower version:
// document["hello"].SetString(buffer, document.GetAllocator());
// Constructor version:
// Value author(buffer, len, document.GetAllocator());
// Value author(buffer, document.GetAllocator());
memset
(
buffer
,
0
,
sizeof
(
buffer
));
// For demonstration purpose.
}
// Variable 'buffer' is unusable now but 'author' has already made a copy.
json
.
AddMember
(
"author"
,
author
,
json
.
GetAllocator
());
assert
(
author
.
IsNull
());
// Move semantic for assignment. After this variable is assigned as a member, the variable becomes null.
std
::
cout
<<
"
\n
Modified JSON with reformatting:
\n
"
;
rapidjson
::
StringBuffer
sb
;
rapidjson
::
PrettyWriter
<
rapidjson
::
StringBuffer
>
writer
(
sb
);
json
.
Accept
(
writer
);
// Accept() traverses the DOM and generates Handler events.
return
sb
.
GetString
();
}
src/Switch.h
View file @
da8ac53f
...
...
@@ -10,11 +10,38 @@
#include
<string>
#include
<map>
#include
"Types/Types.h"
#include
"../include/rapidjson/document.h"
#include
"../include/rapidjson/prettywriter.h"
#include
"Types.h"
#define DEFAULT_USER "admin"
#define DEFAULT_PASS "admin"
typedef
rapidjson
::
Value
jsonNode
;
/*
template<typename T>
jsonNode to_json(const T &x) {
// TODO Throw undefined
return NULL;
}
template<> jsonNode to_json<vlan>(const vlan &x) {
jsonNode ret;
return ret;
}
template<typename T>
T from_json(const jsonNode &s) {
// TODO Throw not implemented
return NULL;
}
template<> vlan from_json<vlan>(const jsonNode &s) {
vlan ret;
return ret;
}*/
struct
vlan
{
int
vlan_id
;
std
::
string
name
;
...
...
@@ -34,8 +61,10 @@ class Switch {
public:
Switch
()
{
}
void
parse
(
datasets
);
void
parse
(
dataset
);
int
parse
(
datasets
);
int
parse
(
dataset
);
int
parse
(
std
::
string
);
std
::
string
toString
();
struct
{
std
::
string
type
;
std
::
string
hardware_version
;
...
...
@@ -52,6 +81,7 @@ public:
bool
dhcp
;
}
settings
;
private:
rapidjson
::
Document
json
;
std
::
vector
<
vlan
>
vlans
;
std
::
vector
<
port
>
ports
;
};
...
...
src/Types/Types.h
deleted
100644 → 0
View file @
ff585313
/*
* Types.h
*
* Created on: 11.09.2015
* Author: jdi
*/
#ifndef TYPES_H_
#define TYPES_H_
#include
<initializer_list>
#include
<algorithm>
#include
<iostream>
#include
<iomanip>
#include
<vector>
#include
<array>
#include
"bytes.h"
#include
"datasets.h"
class
macAddr
:
public
std
::
array
<
byte
,
6
>
{
public:
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
out
,
const
macAddr
&
arr
)
{
out
<<
std
::
hex
<<
std
::
setw
(
2
)
<<
std
::
setfill
(
'0'
)
<<
(
unsigned
)
arr
[
0
];
for
(
unsigned
i
=
1
;
i
<
6
;
i
++
)
{
out
<<
":"
<<
std
::
setw
(
2
)
<<
std
::
setfill
(
'0'
)
<<
(
unsigned
)
arr
[
i
];
}
return
out
;
}
macAddr
()
{
*
this
=
{
0
,
0
,
0
,
0
,
0
,
0
};
}
macAddr
(
std
::
initializer_list
<
byte
>
s
)
{
int
i
=
0
;
for
(
byte
b
:
s
)
{
if
(
i
<
6
)
(
*
this
)[
i
++
]
=
b
;
else
break
;
}
}
macAddr
(
bytes
bts
)
{
int
i
=
0
;
for
(
byte
b
:
bts
)
{
if
(
i
<
6
)
(
*
this
)[
i
++
]
=
b
;
else
break
;
}
}
};
class
ipAddr
:
public
std
::
array
<
byte
,
4
>
{
public:
ipAddr
()
{
*
this
=
{
0
,
0
,
0
,
0
,
0
,
0
};
}
ipAddr
(
std
::
initializer_list
<
byte
>
s
)
{
int
i
=
0
;
for
(
byte
b
:
s
)
{
if
(
i
<
4
)
(
*
this
)[
i
++
]
=
b
;
else
break
;
}
}
ipAddr
(
bytes
bts
)
{
int
i
=
0
;
for
(
byte
b
:
bts
)
{
if
(
i
<
4
)
(
*
this
)[
i
++
]
=
b
;
else
break
;
}
}
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
out
,
ipAddr
&
arr
)
{
out
<<
std
::
dec
<<
(
unsigned
)
arr
[
0
];
for
(
unsigned
i
=
1
;
i
<
4
;
i
++
)
{
out
<<
"."
<<
(
unsigned
)
arr
[
i
];
}
return
out
;
}
};
template
<
typename
T
>
std
::
vector
<
T
>
operator
+
(
const
std
::
vector
<
T
>
&
A
,
const
std
::
vector
<
T
>
&
B
)
{
std
::
vector
<
T
>
AB
;
AB
.
reserve
(
A
.
size
()
+
B
.
size
());
// preallocate memory
AB
.
insert
(
AB
.
end
(),
A
.
begin
(),
A
.
end
());
// add A;
AB
.
insert
(
AB
.
end
(),
B
.
begin
(),
B
.
end
());
// add B;
return
AB
;
}
template
<
typename
T
>
std
::
vector
<
T
>
&
operator
+=
(
std
::
vector
<
T
>
&
A
,
const
std
::
vector
<
T
>
&
B
)
{
A
.
reserve
(
A
.
size
()
+
B
.
size
());
A
.
insert
(
A
.
end
(),
B
.
begin
(),
B
.
end
());
return
A
;
}
struct
Options
{
unsigned
flags
=
0x00
;
std
::
string
user
;
std
::
string
password
;
std
::
string
interface
;