mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 10:45:57 +01:00
Compare commits
584 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3aedc56ed | ||
|
|
3b006c15db | ||
|
|
177d0b4621 | ||
|
|
24ac038c30 | ||
|
|
a619e4ff98 | ||
|
|
14bb185d7a | ||
|
|
137b56d5a7 | ||
|
|
ed2b3c12d5 | ||
|
|
1650b60234 | ||
|
|
c20c82bcb5 | ||
|
|
5858132261 | ||
|
|
16f5795243 | ||
|
|
e90e377b73 | ||
|
|
222611b377 | ||
|
|
b447c664e1 | ||
|
|
468159e6d2 | ||
|
|
cd40b232e7 | ||
|
|
1166094a2f | ||
|
|
b3d874d6a8 | ||
|
|
553b1fb255 | ||
|
|
94939dd0fa | ||
|
|
0774a8dcad | ||
|
|
f46dee9f19 | ||
|
|
5b082a82b2 | ||
|
|
07012648fb | ||
|
|
ce409dbc7e | ||
|
|
16e77146ab | ||
|
|
a87c4a64f5 | ||
|
|
9e61286a59 | ||
|
|
8da102fb48 | ||
|
|
750c3556d9 | ||
|
|
28663b0e93 | ||
|
|
731e36e373 | ||
|
|
608b48f25c | ||
|
|
de247fcbc8 | ||
|
|
7bc4d38470 | ||
|
|
a926b75224 | ||
|
|
064439236c | ||
|
|
0c40a0714b | ||
|
|
d74520768b | ||
|
|
3385df9cc9 | ||
|
|
18c31b20f5 | ||
|
|
7387912ca1 | ||
|
|
0d52763a61 | ||
|
|
86b505f998 | ||
|
|
62a803c55c | ||
|
|
0573808aeb | ||
|
|
22b4435c81 | ||
|
|
b803959e11 | ||
|
|
2f16497bf8 | ||
|
|
78aa7d1787 | ||
|
|
ba2216e6e9 | ||
|
|
74e3d909e6 | ||
|
|
5e52091ecf | ||
|
|
dafb299ea3 | ||
|
|
659bec56d7 | ||
|
|
8c1bea6f84 | ||
|
|
d8d1dc003b | ||
|
|
c2bb52b82f | ||
|
|
1f5456b18b | ||
|
|
dc702f4fd6 | ||
|
|
2a8101eef3 | ||
|
|
20702ddaff | ||
|
|
f4e2701705 | ||
|
|
776ae4e83b | ||
|
|
2158c7a92e | ||
|
|
b53bad7b29 | ||
|
|
6c92bcdad1 | ||
|
|
b949e56d15 | ||
|
|
18ff3e7b6a | ||
|
|
559b1fb89a | ||
|
|
1e78ef0752 | ||
|
|
602ada7820 | ||
|
|
57ac099703 | ||
|
|
eb7628eca4 | ||
|
|
c26e4943c2 | ||
|
|
7e90c8be6a | ||
|
|
3659d89c25 | ||
|
|
db992d42e5 | ||
|
|
5571a270d4 | ||
|
|
b18c2cefec | ||
|
|
3f204321ce | ||
|
|
63603b8ac8 | ||
|
|
fa79582b89 | ||
|
|
342e2c77a7 | ||
|
|
7848e28b62 | ||
|
|
544aa1b339 | ||
|
|
de4791f0c7 | ||
|
|
915f506f3a | ||
|
|
f29566d6d9 | ||
|
|
e4f747164c | ||
|
|
683550b297 | ||
|
|
971fdf7d1c | ||
|
|
1038c6f7f3 | ||
|
|
8efc0271f5 | ||
|
|
9ac5e597e6 | ||
|
|
f7fc5fae1d | ||
|
|
f44b253a42 | ||
|
|
8f85a6e557 | ||
|
|
8fd25e23a6 | ||
|
|
a3dd057147 | ||
|
|
e16fe46d7a | ||
|
|
39f3b24058 | ||
|
|
8e50756afa | ||
|
|
c07cd40234 | ||
|
|
d2addea9cf | ||
|
|
f88c024b2f | ||
|
|
983325bfdf | ||
|
|
f4635a696e | ||
|
|
c439eccdf8 | ||
|
|
04e29858ee | ||
|
|
ab2850e22e | ||
|
|
6429dcd03f | ||
|
|
b43d2f74e4 | ||
|
|
2aab4cf126 | ||
|
|
f2766db829 | ||
|
|
db0fb7f20d | ||
|
|
a6817528bc | ||
|
|
a7dd867503 | ||
|
|
e48f64daac | ||
|
|
171067eb22 | ||
|
|
78b94fa350 | ||
|
|
c84652af40 | ||
|
|
19fd9a7c1d | ||
|
|
5df1c354f0 | ||
|
|
eb0d82ce89 | ||
|
|
f89e922d72 | ||
|
|
ecacd4aee5 | ||
|
|
a17ec89332 | ||
|
|
7003541284 | ||
|
|
87c0e3a337 | ||
|
|
cfb9b646cc | ||
|
|
eed8229a04 | ||
|
|
3e6e25d0aa | ||
|
|
77ca5c2701 | ||
|
|
ca3127ffbc | ||
|
|
77d965784e | ||
|
|
edd289c645 | ||
|
|
2f528876ad | ||
|
|
aa64e34880 | ||
|
|
5fcde41023 | ||
|
|
63e22fc349 | ||
|
|
7af1ec0984 | ||
|
|
4e95797710 | ||
|
|
a641589b09 | ||
|
|
b8e4c7248b | ||
|
|
d29296935e | ||
|
|
1da2c1dcdc | ||
|
|
76395370de | ||
|
|
7589a0a108 | ||
|
|
34072f733c | ||
|
|
9442233a8a | ||
|
|
993831709d | ||
|
|
4def995185 | ||
|
|
fa85aa3f8b | ||
|
|
8021112fea | ||
|
|
80f424b6b3 | ||
|
|
1ef5be352a | ||
|
|
1a83801722 | ||
|
|
3c2f40ec02 | ||
|
|
b47dc3f77c | ||
|
|
f1e726f503 | ||
|
|
afb6ad488c | ||
|
|
5d68211af2 | ||
|
|
887bccf0af | ||
|
|
7eb067338f | ||
|
|
6896cc6346 | ||
|
|
de2f29b797 | ||
|
|
1ec6006f33 | ||
|
|
d9f92c46c4 | ||
|
|
9677c06036 | ||
|
|
a07b3e8a3a | ||
|
|
58a4d336b9 | ||
|
|
86da3818ff | ||
|
|
815889bd22 | ||
|
|
be48947ead | ||
|
|
3e7188edf7 | ||
|
|
3d4f9285c9 | ||
|
|
e556f4147f | ||
|
|
4e4f7a2390 | ||
|
|
35e65d018c | ||
|
|
714b8d9810 | ||
|
|
d061fced7e | ||
|
|
36fedf4f65 | ||
|
|
89202c5dd5 | ||
|
|
110adc58dc | ||
|
|
6f32a1982a | ||
|
|
c50c4c105c | ||
|
|
ac69278676 | ||
|
|
af325f00d9 | ||
|
|
28fa1b2f7e | ||
|
|
ab51787323 | ||
|
|
92bda42ac1 | ||
|
|
730e69463c | ||
|
|
07f000f65a | ||
|
|
3e7d30e01c | ||
|
|
22c72955f5 | ||
|
|
6f681f6519 | ||
|
|
c7273ddd30 | ||
|
|
2c6ef2a5c0 | ||
|
|
4eb4dfe5fa | ||
|
|
8838ddf921 | ||
|
|
6b3875ae39 | ||
|
|
ab763f25a4 | ||
|
|
550eea98b1 | ||
|
|
ecfed8db44 | ||
|
|
fe6e575158 | ||
|
|
d0b4383a0d | ||
|
|
83e2c8dc47 | ||
|
|
57787649d7 | ||
|
|
c9e7237184 | ||
|
|
52be4b0e8a | ||
|
|
e1571e19a8 | ||
|
|
8c7bf7d779 | ||
|
|
406e458c3a | ||
|
|
3f26974563 | ||
|
|
988f2382c4 | ||
|
|
b983fe0bb3 | ||
|
|
5a3f3e43a6 | ||
|
|
49d6e42324 | ||
|
|
d7a7877bfe | ||
|
|
d8ead95070 | ||
|
|
5404e9f004 | ||
|
|
f0aaec98f3 | ||
|
|
348371e43c | ||
|
|
4763486523 | ||
|
|
7250c7a03d | ||
|
|
cedd127e8f | ||
|
|
fcad90b5e9 | ||
|
|
64778f5412 | ||
|
|
a5766a19c2 | ||
|
|
c6f4e816aa | ||
|
|
ce6ef3186b | ||
|
|
6a66008153 | ||
|
|
6c6b345ba0 | ||
|
|
734b874dab | ||
|
|
6d573d8327 | ||
|
|
11eca1816a | ||
|
|
b0d66a01d2 | ||
|
|
bd0db1354e | ||
|
|
01475679d1 | ||
|
|
b2173ffb86 | ||
|
|
3f2f6438fd | ||
|
|
60b5f3e6e4 | ||
|
|
82e97addb1 | ||
|
|
19ae1f366b | ||
|
|
a9747a349a | ||
|
|
fe38bba477 | ||
|
|
a20f9d3e81 | ||
|
|
39e9f0542d | ||
|
|
1c2c5d7dd4 | ||
|
|
1c2ac61bb0 | ||
|
|
f764f68e9c | ||
|
|
2453e57436 | ||
|
|
500ef1088b | ||
|
|
c83cff36d8 | ||
|
|
589adba798 | ||
|
|
6e1d1d3dc4 | ||
|
|
ec59194232 | ||
|
|
7de4474996 | ||
|
|
95626a867e | ||
|
|
c072ffe421 | ||
|
|
ac797a836e | ||
|
|
0cda2287a8 | ||
|
|
6bfc0c84f0 | ||
|
|
1bd0cd504e | ||
|
|
a3e863942b | ||
|
|
f88cf9b025 | ||
|
|
1ad245238f | ||
|
|
4c54a69e64 | ||
|
|
77a31ca6b5 | ||
|
|
c06787ca22 | ||
|
|
15a353c123 | ||
|
|
1b4d22314d | ||
|
|
35383ac359 | ||
|
|
d2b00990fe | ||
|
|
97a11073d4 | ||
|
|
95b6261324 | ||
|
|
37c92fcf5c | ||
|
|
18281e614d | ||
|
|
7f8644cb39 | ||
|
|
799ba2b4b6 | ||
|
|
ad0a1ca97d | ||
|
|
7607610cf9 | ||
|
|
a71a3d29ff | ||
|
|
9051197603 | ||
|
|
94e5ac2109 | ||
|
|
84cb686928 | ||
|
|
da07ad3b13 | ||
|
|
d5cba00ce0 | ||
|
|
ba9d0b34c6 | ||
|
|
f2850cc0b9 | ||
|
|
c69ea0c1fb | ||
|
|
a63387f85e | ||
|
|
df7e7b391d | ||
|
|
5d6431d2d9 | ||
|
|
a61a361eb1 | ||
|
|
9dbad2a26f | ||
|
|
aaba3dd46a | ||
|
|
2e013847d9 | ||
|
|
22e569d430 | ||
|
|
2847039ffe | ||
|
|
54ce11629c | ||
|
|
8dcfd6aae0 | ||
|
|
838a4a5cb9 | ||
|
|
e82b72e931 | ||
|
|
fdc6ccdf5c | ||
|
|
52b389afe8 | ||
|
|
552006c876 | ||
|
|
f0b32edaa9 | ||
|
|
5a901ca155 | ||
|
|
9593cf4cf6 | ||
|
|
64725e2ed9 | ||
|
|
9260f9374a | ||
|
|
2ccf50db3e | ||
|
|
e843ee7117 | ||
|
|
a192e814bf | ||
|
|
ccda631708 | ||
|
|
1552e33c67 | ||
|
|
8afc784956 | ||
|
|
5b00916f83 | ||
|
|
6b7bc76603 | ||
|
|
732c665af5 | ||
|
|
8cf367d68c | ||
|
|
d070978a54 | ||
|
|
7f30efab38 | ||
|
|
d7fed87ebb | ||
|
|
269ac164ed | ||
|
|
55edf31aa6 | ||
|
|
364782b8af | ||
|
|
d3c576f6de | ||
|
|
8d52d73968 | ||
|
|
48022d3a3f | ||
|
|
ec1634d6d8 | ||
|
|
688bb7094e | ||
|
|
928e66eb27 | ||
|
|
d80c27de29 | ||
|
|
6aac22fa74 | ||
|
|
7bc1ab41f7 | ||
|
|
068e304baa | ||
|
|
5dc7b20a43 | ||
|
|
a70ce10bed | ||
|
|
3773443fc8 | ||
|
|
1f4be63d08 | ||
|
|
6a69d1ff6c | ||
|
|
85102b4546 | ||
|
|
f188ea4d2a | ||
|
|
a75dd9e3f9 | ||
|
|
dda673cad4 | ||
|
|
8b125d31f2 | ||
|
|
67ee3e8a7d | ||
|
|
d70536f9ab | ||
|
|
bfe9f9f4a5 | ||
|
|
97e24131c6 | ||
|
|
42b6c40433 | ||
|
|
4dcef0f15d | ||
|
|
c082dfad67 | ||
|
|
331bc57b44 | ||
|
|
b7e20f550e | ||
|
|
e15ef0d837 | ||
|
|
08fd9e2d69 | ||
|
|
3a99213c0b | ||
|
|
ad71158268 | ||
|
|
186d23c920 | ||
|
|
cfbf88bb5f | ||
|
|
1681981fe8 | ||
|
|
3e84b07a01 | ||
|
|
b087c964d4 | ||
|
|
bf70a94921 | ||
|
|
e5282f8a3c | ||
|
|
5920185288 | ||
|
|
92f0249d2b | ||
|
|
016cfeecc6 | ||
|
|
8bf0c355f4 | ||
|
|
fa4178de09 | ||
|
|
04578b109f | ||
|
|
9dabb6f570 | ||
|
|
8812153491 | ||
|
|
17da10d76e | ||
|
|
dae25b3381 | ||
|
|
745071af65 | ||
|
|
f3448f1797 | ||
|
|
dad6091706 | ||
|
|
6d6eb9c5d7 | ||
|
|
64b84fa91d | ||
|
|
bac8388cec | ||
|
|
e69d0d7ce9 | ||
|
|
b326546229 | ||
|
|
5c22cc7985 | ||
|
|
bd31b3648f | ||
|
|
3c595e6225 | ||
|
|
ed40dd423d | ||
|
|
0e5d7d7ae0 | ||
|
|
9ef6f7a612 | ||
|
|
da923aa63c | ||
|
|
f88d94cbaa | ||
|
|
6403d1908d | ||
|
|
423dbf2404 | ||
|
|
af6b0fdbb2 | ||
|
|
8e7eb25558 | ||
|
|
91a724fe2d | ||
|
|
eb1c43d293 | ||
|
|
4123764a48 | ||
|
|
abe94ece52 | ||
|
|
2498ebf7d6 | ||
|
|
f8445c2e5c | ||
|
|
116eb9f1c1 | ||
|
|
48c068b84a | ||
|
|
20a3868e82 | ||
|
|
85d7401520 | ||
|
|
3b848060aa | ||
|
|
69fc5ff54b | ||
|
|
8db6032303 | ||
|
|
549c0e97d0 | ||
|
|
c3861cf54e | ||
|
|
7c1453662f | ||
|
|
5b60b79fd8 | ||
|
|
07b5d74179 | ||
|
|
76b0c919b9 | ||
|
|
785ee7b47b | ||
|
|
64b267c7ea | ||
|
|
0832184896 | ||
|
|
5d41316b9a | ||
|
|
602ead5de5 | ||
|
|
72e038b9bf | ||
|
|
4b0976571e | ||
|
|
8ab48106d6 | ||
|
|
3036f9ce91 | ||
|
|
88d8f99676 | ||
|
|
fb4e5086fd | ||
|
|
58e3a7a687 | ||
|
|
f54399c45c | ||
|
|
0cf3dd3342 | ||
|
|
d7df3a449e | ||
|
|
dc1a5a6982 | ||
|
|
3d21ad7bec | ||
|
|
757e54dc08 | ||
|
|
ced645fb02 | ||
|
|
c1e479f523 | ||
|
|
ca56cc10dd | ||
|
|
75add84741 | ||
|
|
3d3d7b8506 | ||
|
|
b21154a926 | ||
|
|
2169b1f71f | ||
|
|
d84f10cf08 | ||
|
|
f5a82b1a17 | ||
|
|
2c16aaaecd | ||
|
|
d7e0d17154 | ||
|
|
2b7714500c | ||
|
|
03ad7f3ae7 | ||
|
|
756dd97fc7 | ||
|
|
7bffa7801d | ||
|
|
4ba9085eeb | ||
|
|
c4a2fed112 | ||
|
|
df3bca099a | ||
|
|
53e2c58f0b | ||
|
|
d7a9816246 | ||
|
|
67d31fd62c | ||
|
|
afe778d03c | ||
|
|
7a2ae6b7d5 | ||
|
|
481c51b4c7 | ||
|
|
38239be472 | ||
|
|
31ca9a6cc8 | ||
|
|
49af3714e8 | ||
|
|
36216107ec | ||
|
|
02e2b278de | ||
|
|
9750f46c6d | ||
|
|
13c05fbdb1 | ||
|
|
6d90b0ce32 | ||
|
|
6b82e50c03 | ||
|
|
530cc56922 | ||
|
|
0a16d8f462 | ||
|
|
e3c382efa0 | ||
|
|
fb43cb738b | ||
|
|
6e026fcb66 | ||
|
|
187e7b1ca3 | ||
|
|
8aff1b4afe | ||
|
|
45546eee39 | ||
|
|
a35b086d12 | ||
|
|
3e23bcc73c | ||
|
|
35d5045db4 | ||
|
|
65b7919ebf | ||
|
|
4b9f998784 | ||
|
|
b07deba105 | ||
|
|
534bdaf30b | ||
|
|
87c4963533 | ||
|
|
978041a9a2 | ||
|
|
30445f1e97 | ||
|
|
693cef04df | ||
|
|
9d0a2d4f3e | ||
|
|
2cf61403e1 | ||
|
|
69b26bd637 | ||
|
|
cec69ee261 | ||
|
|
891f4ac4d7 | ||
|
|
af71a4eca7 | ||
|
|
dd0b9ecde4 | ||
|
|
6dec68128d | ||
|
|
ab61907a06 | ||
|
|
9c9994f129 | ||
|
|
97e6a99c5e | ||
|
|
d09450980a | ||
|
|
79c0023f75 | ||
|
|
3b23d68a10 | ||
|
|
fe48586eef | ||
|
|
848d8348ae | ||
|
|
da3bf12671 | ||
|
|
d447009779 | ||
|
|
2c2c92325d | ||
|
|
b451a9eae0 | ||
|
|
c42c18f5df | ||
|
|
8bb837eda8 | ||
|
|
6b6636b0bb | ||
|
|
316bb12946 | ||
|
|
cab0ba8b9a | ||
|
|
0a2fdfcd42 | ||
|
|
43217549eb | ||
|
|
0f3441ccf6 | ||
|
|
9c25f635eb | ||
|
|
3ec8ab868e | ||
|
|
8d28bfe7a1 | ||
|
|
46f5d7a0cd | ||
|
|
8400079bce | ||
|
|
68c750810f | ||
|
|
0dee5618f2 | ||
|
|
76c6511e0c | ||
|
|
2f2a705127 | ||
|
|
b0faebd135 | ||
|
|
2bf2b222e0 | ||
|
|
c42cd0114f | ||
|
|
5cd0c8e41b | ||
|
|
8276dca22e | ||
|
|
d4e632f513 | ||
|
|
325de4abca | ||
|
|
e651770018 | ||
|
|
d1ffecb132 | ||
|
|
460e87cb43 | ||
|
|
a607ab380c | ||
|
|
a7a63483df | ||
|
|
9de57e1b23 | ||
|
|
f229f9a81e | ||
|
|
62260ab93b | ||
|
|
c108f6e4e6 | ||
|
|
5c8fdd2b6c | ||
|
|
34bf1f23f7 | ||
|
|
ae503523e4 | ||
|
|
e64e0ce27b | ||
|
|
93ed4f537e | ||
|
|
995abd4d00 | ||
|
|
0dcbe6ffbe | ||
|
|
745ebfb904 | ||
|
|
c5b9afaf83 | ||
|
|
f4ccba93e6 | ||
|
|
308cbcdc40 | ||
|
|
eb5598be7c | ||
|
|
830da2488b | ||
|
|
530ac79ba4 | ||
|
|
213b812520 | ||
|
|
8c2b56e286 | ||
|
|
147c1a4315 | ||
|
|
2fa4c2ade3 | ||
|
|
621af33a81 | ||
|
|
0d9fe13166 | ||
|
|
1a9cd63397 | ||
|
|
e2f96123a3 | ||
|
|
96fc1a3749 | ||
|
|
f2ed64293b | ||
|
|
bf807be7bd | ||
|
|
437911eacd | ||
|
|
2d89f1548d | ||
|
|
c8b3b8d2b8 | ||
|
|
7d7aae5929 | ||
|
|
fc950f643b | ||
|
|
4bfec7b358 | ||
|
|
3478c7b09a | ||
|
|
a326463160 | ||
|
|
ebad686987 | ||
|
|
3791fc0ee6 | ||
|
|
40a8354125 | ||
|
|
bb683c9f79 | ||
|
|
5edd5932ba | ||
|
|
021f596cf0 | ||
|
|
992d187b04 | ||
|
|
d6d2434482 | ||
|
|
811270760a |
4
.gitmodules
vendored
Normal file
4
.gitmodules
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
[submodule "googletest"]
|
||||
path = googletest
|
||||
url = https://github.com/google/googletest.git
|
||||
ignore = dirty
|
||||
27
.travis.yml
Normal file
27
.travis.yml
Normal file
@@ -0,0 +1,27 @@
|
||||
language: cpp
|
||||
|
||||
sudo: false
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libpcap-dev
|
||||
- libssl-dev
|
||||
- libboost-all-dev
|
||||
|
||||
before_script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake .. -DLIBTINS_ENABLE_CXX11=1
|
||||
- make tests
|
||||
|
||||
script:
|
||||
- ctest -V
|
||||
9
AUTHORS
9
AUTHORS
@@ -1,9 +0,0 @@
|
||||
# Below is a list of people and organizations that have contributed source
|
||||
# code to libtins. Names are listed using the following format:
|
||||
#
|
||||
# Name/Organization <email address>
|
||||
|
||||
Matias Fontanini <matias.fontanini@gmail.com>
|
||||
Santiago Alessandri <san.lt.ss@gmail.com>
|
||||
Bruno Nery <brunonery@brunonery.com>
|
||||
Piotr Haber <piotr.haber@sens.us>
|
||||
339
CHANGES
339
CHANGES
@@ -1,339 +0,0 @@
|
||||
v3.2
|
||||
|
||||
- Added include guard for config.h.
|
||||
|
||||
- The functor used on BaseSniffer::sniff_loop can now take a Packet.
|
||||
|
||||
- Added mcs, tx_flags, ext and data_retries options to RadioTap.
|
||||
|
||||
- Fixed big endian representation of RadioTap header.
|
||||
|
||||
- RadioTap's dbm_signal and dbm_noise are now signed.
|
||||
|
||||
- RadioTap now throws if an option is not present when getting
|
||||
its value.
|
||||
|
||||
- TKIP decryption now works correctly on packets from AP to STA.
|
||||
|
||||
- Added support for PKTAP header.
|
||||
|
||||
- Fixed endian issue on IPv4Address::ip_to_int on Windows.
|
||||
|
||||
- Fixed IP parsing when total length is 0 due to TCP segmentation offload.
|
||||
|
||||
- Re-added support for pkg-config.
|
||||
|
||||
- TCPStreamFollower now calls PDU::find_pdu instead of PDU::rfind_pdu.
|
||||
|
||||
- Fixed assertion throw caused by DNS parsing on Windows on debug mode.
|
||||
|
||||
- Added throw on BSD when trying to send_recv L3 packets.
|
||||
|
||||
- Added Loopback::matches_response.
|
||||
|
||||
- Removed obsolete autotools files.
|
||||
|
||||
- Fixed exception thrown when an interface didn't have an IP address
|
||||
on NetworkInterface.
|
||||
|
||||
- Added NetworkInterface::is_loopback.
|
||||
|
||||
- Moved all headers to the directory include/tins.
|
||||
|
||||
- Fixed compilation warning on TCPStramFollower due to signed to unsigned
|
||||
conversion on integral constant.
|
||||
|
||||
- BaseSniffer::get_pcap_handle is now public.
|
||||
|
||||
- PPPoE session packets are now parsed correctly.
|
||||
|
||||
- Fixed invalid Loopback protocol detection on FreeBSD/OSX.
|
||||
|
||||
- Fixed OSX IP packet sending issue.
|
||||
|
||||
- Added useful constructors to RawPDU.
|
||||
|
||||
- Fixed compilation errors on FreeBSD.
|
||||
|
||||
- Improved documentation on several classes.
|
||||
|
||||
- Fixed parsing bug when allocating IP over IP packets.
|
||||
|
||||
- Fixed Windows network interface naming.
|
||||
|
||||
- Utils::network_interface returns pcap compatible names on Windows.
|
||||
|
||||
- NetworkInterface::name now works on Windows.
|
||||
|
||||
- Added documentation generation through the build system.
|
||||
|
||||
- Added SnifferConfiguration class.
|
||||
|
||||
- Fixed bug on Dot3 serialization.
|
||||
|
||||
- Added OfflinePacketFilter class.
|
||||
|
||||
- Renamed NOEXCEPT macro to TINS_NOEXCEPT.
|
||||
|
||||
- Added DataLinkType class.
|
||||
|
||||
- IPv4Address now uses inet_pton when constructing from string.
|
||||
|
||||
v3.1 - Sun Aug 24 21:39:43 ART 2014
|
||||
|
||||
- Fixed ICMPv6 checksum error on serialization.
|
||||
|
||||
- Fixed empty domain name encoding on DNS.
|
||||
|
||||
- Changed the build system to CMake.
|
||||
|
||||
v3.0 - Thu Aug 7 21:39:09 ART 2014
|
||||
|
||||
- Timestamps can now be constructed from std::chrono::duration.
|
||||
|
||||
- Packets can now be constructed from a PDU pointer and take ownership
|
||||
of it.
|
||||
|
||||
- All protocols now set the next layer protocol flag, regardless if
|
||||
it was already set. This was not done in some protocols,
|
||||
like EthernetII, and as a consequence if the network layer protocol
|
||||
was replaced by other, the packet would be serialized incorrectly.
|
||||
|
||||
- Fixed invalid parsing of some unknown DNS records.
|
||||
|
||||
- Fixed unaligned memory accesses that were not supported under
|
||||
ARMv4 and ARMv5.
|
||||
|
||||
- Added BaseSniffer::set_extract_raw_pdus.
|
||||
|
||||
- Reduced minimum automake version to 1.11.
|
||||
|
||||
- Added Utils::to_string(PDU::PDUType).
|
||||
|
||||
- Fixed error compilations on Windows.
|
||||
|
||||
- Fixed ICMPv6 checksum calculation.
|
||||
|
||||
- Added method in IP and TCP to emplace an option (C++11 only).
|
||||
|
||||
- Added small option optimization to PDUOption.
|
||||
|
||||
- Fixed error compilation on RSNInformation.
|
||||
|
||||
- Renamed ICMP::check to ICMP::checksum.
|
||||
|
||||
- Added Sniffer support to set interface to promiscuous mode.
|
||||
|
||||
- TCPStreamFollower now handles overlapping fragments correctly.
|
||||
|
||||
- Fixed bugs in TCPStreamFollower which didn't allow it to follow
|
||||
stream correctly.
|
||||
|
||||
- TCPStreamFollower now doesn't clear its state after every call to
|
||||
TCPStreamFollower::follow_streams.
|
||||
|
||||
- Added IPv6 flag check to pdu_flag_to_ip_type.
|
||||
|
||||
- Added DHCP::hostname to extract the hostname options.
|
||||
|
||||
- Removed extra qualifier on SessionKeys::decrypt_unicast which
|
||||
produced compilation errors on some platforms.
|
||||
|
||||
- PacketSender::send now uses PDU::matches_flag to match specific
|
||||
PDU types.
|
||||
|
||||
- Removed 'no newline at end of file' warnings.
|
||||
|
||||
- Fixed bug when calling BIOCIMMEDIATE on *BSD.
|
||||
|
||||
- Fixed bug on PacketSender::send_recv which didn't work under *BSD.
|
||||
|
||||
- Fixed bug triggered by not including the string header.
|
||||
|
||||
v2.0 - Thu Jan 23 11:09:38 ART 2014
|
||||
|
||||
- DNSResourceRecord was removed. Now DNS records are added using
|
||||
DNS::Resource.
|
||||
|
||||
- tins.h now includes ppi.h.
|
||||
|
||||
- Done significant improvements in the speed of DNS parsing.
|
||||
|
||||
- Added PDUOption<>::to<> which converts a PDUOption to a specific type.
|
||||
|
||||
- Layer 3 packets sent using PacketSender::send_recv for which the
|
||||
answer is a different PDU type.
|
||||
|
||||
- ICMP::gateway now uses IPv4Address.
|
||||
|
||||
- Added support for ICMP address mask request/reply.
|
||||
|
||||
- Fixed bug in PacketSender when using send_recv and a layer 2 PDU. The
|
||||
interface in which the packet was sent was not the default_interface
|
||||
set when the sender was constructed.
|
||||
|
||||
- IP packets sent using PacketSender::send_recv now match ICMP
|
||||
responses.
|
||||
|
||||
- Added support for ICMP timestamp request/reply packets.
|
||||
ICMP::matches_response now works with these types of packets as well.
|
||||
|
||||
- Added support for reassembling of fragmented IP packets via the
|
||||
IPv4Reassembler class.
|
||||
|
||||
- Fragmented IP packet's inner_pdu PDUs are not decoded now.
|
||||
|
||||
- Added 1000ms as the default read timeout used when calling
|
||||
pcap_open_live. Added BaseSniffer::set_timeout to modify this parameter.
|
||||
|
||||
- Added the --disable-dot11 configure switch.
|
||||
|
||||
- Added support for IPSec.
|
||||
|
||||
- Fixed bug triggered when ifaddrs::ifa_addr was null in
|
||||
NetworkInterface::addresses.
|
||||
|
||||
- Added another overload of Utils::route_entries which returns the
|
||||
result either than storing it in a parameter.
|
||||
|
||||
- Added ARP monitor, WPS detector, DNS queries sniffer and DNS spoofer
|
||||
examples.
|
||||
|
||||
- Added another Sniffer constructor which doesn't expect the maximum
|
||||
capture size.
|
||||
|
||||
- Added tins_cast as a replacement for dynamic_cast on PDUs.
|
||||
|
||||
v1.2 - Mon oct 7 23:33:49 ART 2013
|
||||
|
||||
- Added BaseSniffer::begin and BaseSniffer::end.
|
||||
|
||||
- BaseSniffer::next_packet uses pcap_loop instead of pcap_next, which
|
||||
doesn't work well on some linux distributions.
|
||||
|
||||
- Added PPI PDU class.
|
||||
|
||||
- Fixed a bug in EthernetII triggered when the size of the whole frame
|
||||
was lower than 60 bytes.
|
||||
|
||||
- Added AddressRange class and IPv4Address, IPv6Address and
|
||||
HWAddress<>::operator/.
|
||||
|
||||
- Added is_broadcast, is_multicast and is_unicast to IPv4, IPv6
|
||||
and HWAddress.
|
||||
|
||||
- Added is_private and is_loopback methods to IPv4 and IPv6 addresses.
|
||||
|
||||
- Done some optimizations on TCP's constructor from buffer.
|
||||
|
||||
- Added helper functions to Dot11Data to retrieve the source,
|
||||
destination and BSSID addresses.
|
||||
|
||||
- Fixed bugs in DNS triggered when parsing MX and unknown records.
|
||||
|
||||
- BaseSniffer::next_packet now iterates until a valid packet is found.
|
||||
|
||||
- TCP::get_flag is now const.
|
||||
|
||||
- The --disable-wpa2 now works as expected.
|
||||
|
||||
v1.1 - Wed Jun 5 09:03:37 ART 2013
|
||||
|
||||
- Implemented std::hash specialization for IPv4, IPv6 and HWAddress<>
|
||||
types.
|
||||
|
||||
- Added a RSNHandshakeCapturer class.
|
||||
|
||||
- Added WPA2Decrypter class.
|
||||
|
||||
- IEEE 802.11 frames are not parsed if the RadioTap FAILED_FCS flag
|
||||
is on.
|
||||
|
||||
- RadioTap now calculates its size everytime it's serialized.
|
||||
|
||||
- Splitted the dot11.h and dot11.cpp files into several files to
|
||||
speed up compilation times.
|
||||
|
||||
- Added HWAddress<>::is_broadcast and HWAddress::operator[].
|
||||
|
||||
- Fixed a bug triggered when parsing Dot11QoSData frames.
|
||||
|
||||
v1.0 - Tue Apr 23 20:40:57 ART 2013
|
||||
|
||||
- Link layer protocol PDUs now don't hold a NetworkInterface. This led
|
||||
to changes in their constructors.
|
||||
|
||||
- Removed the obsolete PDU* parameter taken by several classes'
|
||||
constructors.
|
||||
|
||||
- IP now sets the sender's address automatically when no link layer
|
||||
PDU is used.
|
||||
|
||||
- IP, TCP and UDP now calculate the checksum everytime they're
|
||||
serialized.
|
||||
|
||||
- Added PDU::rfind_pdu.
|
||||
|
||||
- Defined several exception types.
|
||||
|
||||
- Implemented matches_response on several protocols.
|
||||
|
||||
- PacketSender is now movable.
|
||||
|
||||
- Added an overload of add_option that takes an rvalue-reference in IP,
|
||||
TCP, DHCP, ICMPv6 and Dot11.
|
||||
|
||||
- Added support for GNU/kFreeBSD.
|
||||
|
||||
- Removed several deprecated methods, such as PDU::clone_packet.
|
||||
|
||||
- Added PacketSender::send(PDU&, NetworkInterface).
|
||||
|
||||
- Normalized the TLV options naming conventions in all of the classes
|
||||
that used them.
|
||||
|
||||
- Added support for Dot1Q, STP, PPPoE protocols.
|
||||
|
||||
- Made some important optimizations on PDUOption<>'s constructors.
|
||||
|
||||
- Added Utils::resolve_domain and Utils::resolve_domain6
|
||||
|
||||
v0.3 - Thu Jan 31 16:47:27 ART 2013
|
||||
|
||||
- Added IPv6, ICMPv6 and DHCPv6 classes.
|
||||
|
||||
- Added support for Loopback interfaces and the Linux Crooked Capture
|
||||
pseudo protocol.
|
||||
|
||||
- Added support for IPv6 records in DNS.
|
||||
|
||||
- Added Packet/RefPacket class.
|
||||
|
||||
- Added support for FreeBSD, OSX and Windows.
|
||||
|
||||
- Added C++11 move semantics to several classes.
|
||||
|
||||
- Done a complete rewrite of the build system; it now uses libtool.
|
||||
|
||||
- Fixed several bugs in DNS.
|
||||
|
||||
|
||||
v0.2 - Sat Oct 20 11:26:40 2012
|
||||
|
||||
- Added support for big endian architectures.
|
||||
|
||||
- Simplified several interfaces.
|
||||
|
||||
- Added IPv4Address and HWAddress class to simplify handling IP and hardware addresses.
|
||||
|
||||
- Added NetworkInterface class to abstract network interfaces.
|
||||
|
||||
- Added TCPStreamFollower class to follow TCP streams on the fly.
|
||||
|
||||
- Added WEPDecrypter class to decrypt WEP-encrypted 802.11 data frames on the fly.
|
||||
|
||||
- Added several new PDUs: Loopback, IEEE802_3, LLC, DNS.
|
||||
|
||||
- Added support for reading and writing pcap files.
|
||||
|
||||
- Moved to BSD-2 license.
|
||||
781
CHANGES.md
Normal file
781
CHANGES.md
Normal file
@@ -0,0 +1,781 @@
|
||||
##### v4.4 - Thu Feb 17 14:41:59 UTC 2022
|
||||
|
||||
- Add RFC8335 extended echo types to `ICMP` and `ICMPv6` (#426)
|
||||
|
||||
- Handle loops in DNS name decompression (#444)
|
||||
|
||||
- Fix Windows' `interface` macro colliding with uses of that identifier in the code (#458)
|
||||
|
||||
- Sending IPv6 packets to a link-scope destination address now uses the right interface index (#448)
|
||||
|
||||
- Fix incorrect endian being used for ICMP's `gateway` and `address_mask` (#437)
|
||||
|
||||
- Socket in `PacketSender::open_l3_socket` is now closed if `setsockopt` fails (#433)
|
||||
|
||||
- Fix various incorrect doxygen documentation comments (#439).
|
||||
|
||||
- Fix infinite loop when querying the routing table in \*BSD (#427)
|
||||
|
||||
##### v4.3 - Fri Sep 18 03:08:33 UTC 2020
|
||||
|
||||
- Assign a PDUType to `Dot11ControlTA` (#420)
|
||||
|
||||
- Don't consider IPv6 ESP header a normal extension header (#374)
|
||||
|
||||
- Don't include non-existing headers when installed without libpcap (#382)
|
||||
|
||||
- Add `IPv6Address::is_local_unicast` (#369)
|
||||
|
||||
- Fix memory leak in `PacketWriter` (#343)
|
||||
|
||||
- Fix memory leaks in `OfflinePacketFilter` (#343)
|
||||
|
||||
- Fix detection of new TCP stream (#335)
|
||||
|
||||
- Introduce `TCP::has_flags` (#334)
|
||||
|
||||
- Fix padding calculations in RadioTapWriter (#333)
|
||||
|
||||
##### v4.2 - Fri Mar 8 04:15:13 UTC 2019
|
||||
|
||||
- Updated location of installed CMake files in unix systems (#331)
|
||||
|
||||
- Fix check to detect cross compilation (#330)
|
||||
|
||||
- Allow getting a PDU's advertised size and use it in `PacketWriter` (#324)
|
||||
|
||||
- Install DLLs in right directory (#326)
|
||||
|
||||
- Add missing Dot11 tagged option types (#305)
|
||||
|
||||
- Add support for DLT_RAW (#313)
|
||||
|
||||
- Fix potential invalid memory accesses when parsing RadioTap (#322)
|
||||
|
||||
##### v4.1 - Tue Dec 11 02:08:48 UTC 2018
|
||||
|
||||
- Fix serialization for QinQ (#316)
|
||||
|
||||
- Added base class access specifier for socket_close_error (#306)
|
||||
|
||||
- Rewrote hw_address_to_string to not require a stringstream (#299)
|
||||
|
||||
- Make RadioTapParser::skip_to_field check for end of buffer (#296)
|
||||
|
||||
- Ensure local include directory comes before system. (#293)
|
||||
|
||||
- Calculate IP option sizes properly (#288)
|
||||
|
||||
- Add parsing of well known IPv6 extension headers (#287)
|
||||
|
||||
- Add missing operators to address classes (#275)
|
||||
|
||||
- Add version macros in config.h
|
||||
|
||||
- Don't assume IPv6 uses ICMPv6 underneath
|
||||
|
||||
- Allow users to specify library install dir
|
||||
|
||||
- Use Sleep windows function passing milliseconds as parameter
|
||||
|
||||
- Implement IPv6::recv_response
|
||||
|
||||
- Don't use nullptr in non C++11 code
|
||||
|
||||
- Ignore (possibly malformed) options after EOL (#281)
|
||||
|
||||
- Don't include dot11.h in tins.h if it is not configured in the library (#277)
|
||||
|
||||
- Fix memory leak in PDU's move assignment operator
|
||||
|
||||
- Append padding to IPv6 options
|
||||
|
||||
##### v4.0 - Mon Dec 4 00:04:30 UTC 2017
|
||||
|
||||
- Add parent PDU to each PDU.
|
||||
|
||||
- Removed parent PDU parameter on `PDU::write_serialization`.
|
||||
|
||||
- Split `utils.h` into multiple files under the `utils` directory.
|
||||
|
||||
- Split `internals.h` into multiple files under the `detail` directory.
|
||||
|
||||
- Improve compilation times by removing useless include directives.
|
||||
|
||||
- Refactor `PDUOption` conversions so that heavy headers are not included in source file.
|
||||
|
||||
- Use `std::vector` instead of `std::list` in `TCP`, `IP`, `IPv6`, `DHCP`, `DHCPv6`, `DNS`, `LLC`, `Dot11` and `PPPoE`.
|
||||
|
||||
- Improve performance on `IP`, `IPv6` and `TCP` by compiting option sizes during serialization.
|
||||
|
||||
- Minor performance improvements in `DNS`.
|
||||
|
||||
- Fix `IPv6` next header handling. Now each one contains its own type and the next type is only set during serialization for ease of use.
|
||||
|
||||
- Refactor `RadioTap` parsing and serialization using a generic parser/writer.
|
||||
|
||||
- Add `BaseSniffer::set_pcap_sniffing_method` to specify whether `pcap_loop` or `pcap_dispatch` should be used when sniffing.
|
||||
|
||||
- Use `IFF_POINTOPOINT` on BSD when getting broadcast address for an interface.
|
||||
|
||||
- Added cipher and akm suites from 802.11-2016.
|
||||
|
||||
- Add IPv6 layer parsing on `Loopback` packets.
|
||||
|
||||
- Allow serializing `Loopback` on Windows.
|
||||
|
||||
- Use the right flag on `Loopback` for `IPv6`.
|
||||
|
||||
- Use the first fragment as a base when reassembling `IP` packets in `IPv4Reassembler`.
|
||||
|
||||
- Restructure CMake files removing useless `CMakeLists.txt` in `include` paths.
|
||||
|
||||
- Add getter/setter for "more data" field in `Dot11Base`.
|
||||
|
||||
- Implemented matching for ND protocol related ICMPv6 messages.
|
||||
|
||||
- Ensure TCP::OptionTypes has 8-bit range.
|
||||
|
||||
- Add header files into CMake sources so IDE can pick them up.
|
||||
|
||||
- Add MPLS "experimental" field.
|
||||
|
||||
- Fix dhcpv6::duid_type constructor from duid_ll.
|
||||
|
||||
##### v3.5 - Sat Apr 1 09:11:58 PDT 2017
|
||||
|
||||
- Added Utils::route6_entries
|
||||
|
||||
- Allow masking IPv4/6 and hardware addresses via `operator&`
|
||||
|
||||
- Add IPv4Address::from_prefix_length
|
||||
|
||||
- Move `stream_id` into a new file and rename it `StreamIdentifier`
|
||||
|
||||
- Allow disabling TCPIP classes
|
||||
|
||||
- Properly handle out of order SACKs on `AckTracker`
|
||||
|
||||
- Move TCP data tracking into a separate class
|
||||
|
||||
- Allow constructing `StreamIdentifier` from a `Stream`
|
||||
|
||||
- Allow configuring pcap timestamp precision
|
||||
|
||||
- Allow building libtins using MinGW
|
||||
|
||||
- Allow including libtins using `add_subdirectory` via CMake
|
||||
|
||||
- Allow setting customer user data to each TCP stream
|
||||
|
||||
- Allow skipping data forward in TCP streams
|
||||
|
||||
- Allow attaching to already existing TCP streams
|
||||
|
||||
- Fix: AddressRange masks first address as well
|
||||
|
||||
- Fix: Add TINS_API to `IPv4Address::operator<<`, `DataTracker` and `AckTracker`
|
||||
|
||||
- Fix: Don't always set `key_t` to 0 on `RSNEAPOL`
|
||||
|
||||
- Fix: Handle MLDv1 properly on ICMP
|
||||
|
||||
- Fix: Make Utils::resolve_hwaddress work on Windows
|
||||
|
||||
- Fix: Interface was sometimes considered down when it was up (BSD/Linux)
|
||||
|
||||
- Fix: Don't set `Dot1Q`'s payload type if next protocol type is unknown
|
||||
|
||||
- Fix: Use recvfrom on BSD/OSX when capturing layer 3 packets
|
||||
|
||||
- Fix: Make `Timestamp::current_time` work on Windows
|
||||
|
||||
- Fix: Forward `NetworkInterface` argument when calling `PacketSender::send_l2`
|
||||
|
||||
- Fix: `Timestamp` overflow issue
|
||||
|
||||
- Fix: boost's include directories variable incorrectly used on build system
|
||||
|
||||
- Fix: Configuring auto cleanup of `Stream`'s server data not working
|
||||
|
||||
- Fix: Set `EthernetII` payload type to `UNKNOWN` if there's no inner PDU
|
||||
|
||||
- Fix: Set payload type to 0 if there's no inner PDU in `IP`, `Dot1Q` and `IPv6`
|
||||
|
||||
- Fix: Buffer length check issues on `Dot11QosData`
|
||||
|
||||
- Fix: Use AF_INET6 flag when opening L3 IPv6 socket
|
||||
|
||||
- Fix: Check expecter size properly on `DNS::extract_metadata`
|
||||
|
||||
- Fix: several unused parameter warnings
|
||||
|
||||
- Fix: CCMP decryption issue when `Dot11QoSData` has a TID != 0
|
||||
|
||||
##### v3.4 - Wed Mar 9 20:24:54 PST 2016
|
||||
|
||||
- Check the secure bit on HandshakeCapturer to detect 2nd packet
|
||||
|
||||
- Add info members directly into NetworkInterface
|
||||
|
||||
- Add IPv6 addresses to NetworkInterface::Info
|
||||
|
||||
- Make *MemoryStream use size_t rather than uint32_t
|
||||
|
||||
- Add WPA2Decrypter callback interface
|
||||
|
||||
- Set MACOSX_RPATH to ON
|
||||
|
||||
- Don't fail configuration if openssl is missing
|
||||
|
||||
- Build layer 5 as RawPDU if IPv6 has fragment header
|
||||
|
||||
- Fix examples so they build on gcc 4.6
|
||||
|
||||
- Fix flag value for sniffer's immediate mode
|
||||
|
||||
- Fix IP fragment reassemble when packet has flags DF+MF
|
||||
|
||||
- Add extract_metadata to main PDU classes
|
||||
|
||||
- Fix examples to make them work on Windows
|
||||
|
||||
- Use timercmp/sub and std::chrono to subtract timevals on PacketSender
|
||||
|
||||
- Build examples against local libtins build
|
||||
|
||||
- Add uninstall target
|
||||
|
||||
- Prefix HAVE_ config.h macros with TINS_
|
||||
|
||||
- Use compiler intrinsics to swap bytes
|
||||
|
||||
- Use C++11 mode by default
|
||||
|
||||
- Add missing TINS_API to PDU classes.
|
||||
|
||||
- Extend/fix ICMPv6 enum values and unify naming
|
||||
|
||||
- Return an empty string for dot11 ssid, if ssid is present but empty
|
||||
|
||||
- Implement new TCP stream follower mechanism
|
||||
|
||||
- Use ExternalProject_Add rather than including the gtest directory
|
||||
|
||||
- Fix invalid endian on IP fragment offset on OSX
|
||||
|
||||
##### v3.3 - Sun Jan 31 21:06:04 PST 2016
|
||||
|
||||
- Add TCP connection close example
|
||||
|
||||
- Move implementations on utils.h to utils.cpp
|
||||
|
||||
- Add ICMPv6 Multicast Listener Query Messages support
|
||||
|
||||
- Add ICMPv6 Multicast Listener Report Message support
|
||||
|
||||
- Make DNS::Query and DNS::Resource lowercase and deprecate the old names
|
||||
|
||||
- Change DNS::query/resource::type to query_type and deprecate old name
|
||||
|
||||
- Add DNS Start Of Authority parsing and serialization
|
||||
|
||||
- Parse and serialize MX preference field correctly
|
||||
|
||||
- Add NetworkInterface::friendly_name to get Windows friendly names
|
||||
|
||||
- Mask 16 bits on random number generated on traceroute example
|
||||
|
||||
- Fix TCP sequence number addition/subtraction when wrapping around
|
||||
|
||||
- Use 802.1ad protocol flag when seralizing stacked Dot1Q
|
||||
|
||||
- Code cleanup and use same syntax on the entire project
|
||||
|
||||
- Correctly serialize PPPoE session packets
|
||||
|
||||
- Fix IPv6 extension headers parsing/serialization
|
||||
|
||||
- Include examples before src to avoid duplicate tins target issue
|
||||
|
||||
- Add MPLS PDU and hook it up with ICMP extensions
|
||||
|
||||
- Set UDP checksum to 0xffff if it's 0
|
||||
|
||||
- Don't define TINS_STATIC in config.h
|
||||
|
||||
- Fix invalid RSNEAPOL parsing issue
|
||||
|
||||
- Remove special clang on OSX case when building gtest
|
||||
|
||||
- Update pseudoheader_checksum signature
|
||||
|
||||
- Fix overall checksum calculation
|
||||
|
||||
- Set ICMP payload length without padding if no extensions are present
|
||||
|
||||
- Export classes on Windows shared lib builds
|
||||
|
||||
- Use google/googletest submodule and update to HEAD
|
||||
|
||||
- Remove unused cassert header inclusions
|
||||
|
||||
- Add input/output memory stream classes port PDU classes to use them
|
||||
|
||||
- Add extensions for ICMP/ICMPv6
|
||||
|
||||
- Fix RSNInformation issues on big endian architectures
|
||||
|
||||
- Add IP::fragment_offset and IP::flags
|
||||
|
||||
- Don't set Ethernet type if inner PDU type is unknown
|
||||
|
||||
- Don't run IP source address overwrite tests on OSX
|
||||
|
||||
- Always calculate IP/IPv6 checksum
|
||||
|
||||
- Fix invalid constant value on PPPoE
|
||||
|
||||
- Define default constructor for PKTAP
|
||||
|
||||
- Guard 802.11 parsing code on PPI around HAVE_DOT11
|
||||
|
||||
- Fix parsing of Dot11 packets encapsulated on PPI having FCS-at-end
|
||||
|
||||
- Fix DataLinkType typo on doxygen docs
|
||||
|
||||
- Update docs on sniff_loop handle persistency
|
||||
|
||||
- Use uint32_t for DNS resource TTL setter
|
||||
|
||||
- Erase streams when they're reassembed on IPv4Reassembler
|
||||
|
||||
- Make all exceptions derive from exception_base
|
||||
|
||||
- Add remove_option member to IP, TCP, Dot11, ICMPv6, DHCP and DHCPv6
|
||||
|
||||
- Allow HW addresses to be 00:00:00:00:00 on NetworkInterface::info
|
||||
|
||||
- Increment option size when adding a new DHCPv6 option
|
||||
|
||||
- Use NOMINMAX on examples
|
||||
|
||||
- Add metric field to RouteEntry
|
||||
|
||||
- Allow setting immediate mode on Sniffer
|
||||
|
||||
- Use one flags field for all flags on SnifferConfiguration
|
||||
|
||||
- Add ICMP responses example
|
||||
|
||||
- Add interfaces_info example
|
||||
|
||||
- Fix bug on SessionKeys::SessionKeys
|
||||
|
||||
- Fix compilation errors on android platform
|
||||
|
||||
- Fix example compilation on Windows
|
||||
|
||||
- Add PacketWriter::write overload that takes a Packet
|
||||
|
||||
- Use different IP addresses on IP tests depending on OS
|
||||
|
||||
- Allow retrieving keys on WPA2Decrypter
|
||||
|
||||
- Add NetworkInterface::is_up and NetworkInterface::info
|
||||
|
||||
- Add NetworkInterface::Info::is_up
|
||||
|
||||
- Fix compilation warnings on Windows x64
|
||||
|
||||
- Fix FindPCAP.cmake to find winpcap on x64
|
||||
|
||||
- Fix more tests warnings triggered on Windows
|
||||
|
||||
- Fix tests compilation warnings on Windows
|
||||
|
||||
- Fix error on VC triggered by pcap redefining the "inline" keyword
|
||||
|
||||
- Soften DNS parsing rules
|
||||
|
||||
- Replace WIN32 macro with _WIN32
|
||||
|
||||
- Fix IPv6Address::to_string on Windows
|
||||
|
||||
- Fix DNS issues triggered on VC
|
||||
|
||||
- Add google test as git submodule
|
||||
|
||||
- Perserve IP protocol when using RawPDU
|
||||
|
||||
- Use pcap_sendpacket by default to send packets on Windows
|
||||
|
||||
- Don't allow receiving l2 packets on windows
|
||||
|
||||
- Added RadioTap channel map type
|
||||
|
||||
- Made rsn_information() a const member function to make Dot11ManagementFrame
|
||||
immutable
|
||||
|
||||
- Ensure HAVE_CXX11 is checked when defining TINS_IS_CXX11
|
||||
|
||||
- Use one integer field for all flags on TCP
|
||||
|
||||
- Fix invalid DNS IPv4 address parsing on big endian arch
|
||||
|
||||
- Don't compile WPA2 test if LIBTINS_ENABLE_WPA2=0
|
||||
|
||||
- Add Dot11 radio measurement name corresponding to IEEE 802.11-2012
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
##### v3.2 - Fri Mar 20 22:12:23 PST 2015
|
||||
|
||||
- Added include guard for config.h.
|
||||
|
||||
- The functor used on BaseSniffer::sniff_loop can now take a Packet.
|
||||
|
||||
- Added mcs, tx_flags, ext and data_retries options to RadioTap.
|
||||
|
||||
- Fixed big endian representation of RadioTap header.
|
||||
|
||||
- RadioTap's dbm_signal and dbm_noise are now signed.
|
||||
|
||||
- RadioTap now throws if an option is not present when getting
|
||||
its value.
|
||||
|
||||
- TKIP decryption now works correctly on packets from AP to STA.
|
||||
|
||||
- Added support for PKTAP header.
|
||||
|
||||
- Fixed endian issue on IPv4Address::ip_to_int on Windows.
|
||||
|
||||
- Fixed IP parsing when total length is 0 due to TCP segmentation offload.
|
||||
|
||||
- Re-added support for pkg-config.
|
||||
|
||||
- TCPStreamFollower now calls PDU::find_pdu instead of PDU::rfind_pdu.
|
||||
|
||||
- Fixed assertion throw caused by DNS parsing on Windows on debug mode.
|
||||
|
||||
- Added throw on BSD when trying to send_recv L3 packets.
|
||||
|
||||
- Added Loopback::matches_response.
|
||||
|
||||
- Removed obsolete autotools files.
|
||||
|
||||
- Fixed exception thrown when an interface didn't have an IP address
|
||||
on NetworkInterface.
|
||||
|
||||
- Added NetworkInterface::is_loopback.
|
||||
|
||||
- Moved all headers to the directory include/tins.
|
||||
|
||||
- Fixed compilation warning on TCPStramFollower due to signed to unsigned
|
||||
conversion on integral constant.
|
||||
|
||||
- BaseSniffer::get_pcap_handle is now public.
|
||||
|
||||
- PPPoE session packets are now parsed correctly.
|
||||
|
||||
- Fixed invalid Loopback protocol detection on FreeBSD/OSX.
|
||||
|
||||
- Fixed OSX IP packet sending issue.
|
||||
|
||||
- Added useful constructors to RawPDU.
|
||||
|
||||
- Fixed compilation errors on FreeBSD.
|
||||
|
||||
- Improved documentation on several classes.
|
||||
|
||||
- Fixed parsing bug when allocating IP over IP packets.
|
||||
|
||||
- Fixed Windows network interface naming.
|
||||
|
||||
- Utils::network_interface returns pcap compatible names on Windows.
|
||||
|
||||
- NetworkInterface::name now works on Windows.
|
||||
|
||||
- Added documentation generation through the build system.
|
||||
|
||||
- Added SnifferConfiguration class.
|
||||
|
||||
- Fixed bug on Dot3 serialization.
|
||||
|
||||
- Added OfflinePacketFilter class.
|
||||
|
||||
- Renamed NOEXCEPT macro to TINS_NOEXCEPT.
|
||||
|
||||
- Added DataLinkType class.
|
||||
|
||||
- IPv4Address now uses inet_pton when constructing from string.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
##### v3.1 - Sun Aug 24 21:39:43 ART 2014
|
||||
|
||||
- Fixed ICMPv6 checksum error on serialization.
|
||||
|
||||
- Fixed empty domain name encoding on DNS.
|
||||
|
||||
- Changed the build system to CMake.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
##### v3.0 - Thu Aug 7 21:39:09 ART 2014
|
||||
|
||||
- Timestamps can now be constructed from std::chrono::duration.
|
||||
|
||||
- Packets can now be constructed from a PDU pointer and take ownership
|
||||
of it.
|
||||
|
||||
- All protocols now set the next layer protocol flag, regardless if
|
||||
it was already set. This was not done in some protocols,
|
||||
like EthernetII, and as a consequence if the network layer protocol
|
||||
was replaced by other, the packet would be serialized incorrectly.
|
||||
|
||||
- Fixed invalid parsing of some unknown DNS records.
|
||||
|
||||
- Fixed unaligned memory accesses that were not supported under
|
||||
ARMv4 and ARMv5.
|
||||
|
||||
- Added BaseSniffer::set_extract_raw_pdus.
|
||||
|
||||
- Reduced minimum automake version to 1.11.
|
||||
|
||||
- Added Utils::to_string(PDU::PDUType).
|
||||
|
||||
- Fixed error compilations on Windows.
|
||||
|
||||
- Fixed ICMPv6 checksum calculation.
|
||||
|
||||
- Added method in IP and TCP to emplace an option (C++11 only).
|
||||
|
||||
- Added small option optimization to PDUOption.
|
||||
|
||||
- Fixed error compilation on RSNInformation.
|
||||
|
||||
- Renamed ICMP::check to ICMP::checksum.
|
||||
|
||||
- Added Sniffer support to set interface to promiscuous mode.
|
||||
|
||||
- TCPStreamFollower now handles overlapping fragments correctly.
|
||||
|
||||
- Fixed bugs in TCPStreamFollower which didn't allow it to follow
|
||||
stream correctly.
|
||||
|
||||
- TCPStreamFollower now doesn't clear its state after every call to
|
||||
TCPStreamFollower::follow_streams.
|
||||
|
||||
- Added IPv6 flag check to pdu_flag_to_ip_type.
|
||||
|
||||
- Added DHCP::hostname to extract the hostname options.
|
||||
|
||||
- Removed extra qualifier on SessionKeys::decrypt_unicast which
|
||||
produced compilation errors on some platforms.
|
||||
|
||||
- PacketSender::send now uses PDU::matches_flag to match specific
|
||||
PDU types.
|
||||
|
||||
- Removed 'no newline at end of file' warnings.
|
||||
|
||||
- Fixed bug when calling BIOCIMMEDIATE on *BSD.
|
||||
|
||||
- Fixed bug on PacketSender::send_recv which didn't work under *BSD.
|
||||
|
||||
- Fixed bug triggered by not including the string header.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
##### v2.0 - Thu Jan 23 11:09:38 ART 2014
|
||||
|
||||
- DNSResourceRecord was removed. Now DNS records are added using
|
||||
DNS::Resource.
|
||||
|
||||
- tins.h now includes ppi.h.
|
||||
|
||||
- Done significant improvements in the speed of DNS parsing.
|
||||
|
||||
- Added PDUOption<>::to<> which converts a PDUOption to a specific type.
|
||||
|
||||
- Layer 3 packets sent using PacketSender::send_recv for which the
|
||||
answer is a different PDU type.
|
||||
|
||||
- ICMP::gateway now uses IPv4Address.
|
||||
|
||||
- Added support for ICMP address mask request/reply.
|
||||
|
||||
- Fixed bug in PacketSender when using send_recv and a layer 2 PDU. The
|
||||
interface in which the packet was sent was not the default_interface
|
||||
set when the sender was constructed.
|
||||
|
||||
- IP packets sent using PacketSender::send_recv now match ICMP
|
||||
responses.
|
||||
|
||||
- Added support for ICMP timestamp request/reply packets.
|
||||
ICMP::matches_response now works with these types of packets as well.
|
||||
|
||||
- Added support for reassembling of fragmented IP packets via the
|
||||
IPv4Reassembler class.
|
||||
|
||||
- Fragmented IP packet's inner_pdu PDUs are not decoded now.
|
||||
|
||||
- Added 1000ms as the default read timeout used when calling
|
||||
pcap_open_live. Added BaseSniffer::set_timeout to modify this parameter.
|
||||
|
||||
- Added the --disable-dot11 configure switch.
|
||||
|
||||
- Added support for IPSec.
|
||||
|
||||
- Fixed bug triggered when ifaddrs::ifa_addr was null in
|
||||
NetworkInterface::addresses.
|
||||
|
||||
- Added another overload of Utils::route_entries which returns the
|
||||
result either than storing it in a parameter.
|
||||
|
||||
- Added ARP monitor, WPS detector, DNS queries sniffer and DNS spoofer
|
||||
examples.
|
||||
|
||||
- Added another Sniffer constructor which doesn't expect the maximum
|
||||
capture size.
|
||||
|
||||
- Added tins_cast as a replacement for dynamic_cast on PDUs.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
##### v1.2 - Mon oct 7 23:33:49 ART 2013
|
||||
|
||||
- Added BaseSniffer::begin and BaseSniffer::end.
|
||||
|
||||
- BaseSniffer::next_packet uses pcap_loop instead of pcap_next, which
|
||||
doesn't work well on some linux distributions.
|
||||
|
||||
- Added PPI PDU class.
|
||||
|
||||
- Fixed a bug in EthernetII triggered when the size of the whole frame
|
||||
was lower than 60 bytes.
|
||||
|
||||
- Added AddressRange class and IPv4Address, IPv6Address and
|
||||
HWAddress<>::operator/.
|
||||
|
||||
- Added is_broadcast, is_multicast and is_unicast to IPv4, IPv6
|
||||
and HWAddress.
|
||||
|
||||
- Added is_private and is_loopback methods to IPv4 and IPv6 addresses.
|
||||
|
||||
- Done some optimizations on TCP's constructor from buffer.
|
||||
|
||||
- Added helper functions to Dot11Data to retrieve the source,
|
||||
destination and BSSID addresses.
|
||||
|
||||
- Fixed bugs in DNS triggered when parsing MX and unknown records.
|
||||
|
||||
- BaseSniffer::next_packet now iterates until a valid packet is found.
|
||||
|
||||
- TCP::get_flag is now const.
|
||||
|
||||
- The --disable-wpa2 now works as expected.
|
||||
|
||||
v1.1 - Wed Jun 5 09:03:37 ART 2013
|
||||
|
||||
- Implemented std::hash specialization for IPv4, IPv6 and HWAddress<>
|
||||
types.
|
||||
|
||||
- Added a RSNHandshakeCapturer class.
|
||||
|
||||
- Added WPA2Decrypter class.
|
||||
|
||||
- IEEE 802.11 frames are not parsed if the RadioTap FAILED_FCS flag
|
||||
is on.
|
||||
|
||||
- RadioTap now calculates its size everytime it's serialized.
|
||||
|
||||
- Splitted the dot11.h and dot11.cpp files into several files to
|
||||
speed up compilation times.
|
||||
|
||||
- Added HWAddress<>::is_broadcast and HWAddress::operator[].
|
||||
|
||||
- Fixed a bug triggered when parsing Dot11QoSData frames.
|
||||
|
||||
v1.0 - Tue Apr 23 20:40:57 ART 2013
|
||||
|
||||
- Link layer protocol PDUs now don't hold a NetworkInterface. This led
|
||||
to changes in their constructors.
|
||||
|
||||
- Removed the obsolete PDU* parameter taken by several classes'
|
||||
constructors.
|
||||
|
||||
- IP now sets the sender's address automatically when no link layer
|
||||
PDU is used.
|
||||
|
||||
- IP, TCP and UDP now calculate the checksum everytime they're
|
||||
serialized.
|
||||
|
||||
- Added PDU::rfind_pdu.
|
||||
|
||||
- Defined several exception types.
|
||||
|
||||
- Implemented matches_response on several protocols.
|
||||
|
||||
- PacketSender is now movable.
|
||||
|
||||
- Added an overload of add_option that takes an rvalue-reference in IP,
|
||||
TCP, DHCP, ICMPv6 and Dot11.
|
||||
|
||||
- Added support for GNU/kFreeBSD.
|
||||
|
||||
- Removed several deprecated methods, such as PDU::clone_packet.
|
||||
|
||||
- Added PacketSender::send(PDU&, NetworkInterface).
|
||||
|
||||
- Normalized the TLV options naming conventions in all of the classes
|
||||
that used them.
|
||||
|
||||
- Added support for Dot1Q, STP, PPPoE protocols.
|
||||
|
||||
- Made some important optimizations on PDUOption<>'s constructors.
|
||||
|
||||
- Added Utils::resolve_domain and Utils::resolve_domain6
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
##### v0.3 - Thu Jan 31 16:47:27 ART 2013
|
||||
|
||||
- Added IPv6, ICMPv6 and DHCPv6 classes.
|
||||
|
||||
- Added support for Loopback interfaces and the Linux Crooked Capture
|
||||
pseudo protocol.
|
||||
|
||||
- Added support for IPv6 records in DNS.
|
||||
|
||||
- Added Packet/RefPacket class.
|
||||
|
||||
- Added support for FreeBSD, OSX and Windows.
|
||||
|
||||
- Added C++11 move semantics to several classes.
|
||||
|
||||
- Done a complete rewrite of the build system; it now uses libtool.
|
||||
|
||||
- Fixed several bugs in DNS.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
##### v0.2 - Sat Oct 20 11:26:40 2012
|
||||
|
||||
- Added support for big endian architectures.
|
||||
|
||||
- Simplified several interfaces.
|
||||
|
||||
- Added IPv4Address and HWAddress class to simplify handling IP and hardware addresses.
|
||||
|
||||
- Added NetworkInterface class to abstract network interfaces.
|
||||
|
||||
- Added TCPStreamFollower class to follow TCP streams on the fly.
|
||||
|
||||
- Added WEPDecrypter class to decrypt WEP-encrypted 802.11 data frames on the fly.
|
||||
|
||||
- Added several new PDUs: Loopback, IEEE802_3, LLC, DNS.
|
||||
|
||||
- Added support for reading and writing pcap files.
|
||||
|
||||
- Moved to BSD-2 license.
|
||||
276
CMakeLists.txt
276
CMakeLists.txt
@@ -1,22 +1,39 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.1)
|
||||
PROJECT(libtins)
|
||||
|
||||
OPTION(LIBTINS_BUILD_EXAMPLES "Build examples" ON)
|
||||
OPTION(LIBTINS_BUILD_TESTS "Build tests" ON)
|
||||
|
||||
# Compile in release mode by default
|
||||
IF(NOT CMAKE_BUILD_TYPE)
|
||||
MESSAGE(STATUS "Setting build type to 'RelWithDebInfo' as none was specified.")
|
||||
SET(CMAKE_BUILD_TYPE RelWithDebInfo)
|
||||
SET(CMAKE_BUILD_TYPE RelWithDebInfo)
|
||||
ELSE(NOT CMAKE_BUILD_TYPE)
|
||||
MESSAGE(STATUS "Using specified '${CMAKE_BUILD_TYPE}' build type.")
|
||||
ENDIF(NOT CMAKE_BUILD_TYPE)
|
||||
|
||||
# Default compilation settings
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
|
||||
# Compilation flags.
|
||||
IF(MSVC)
|
||||
# Don't always use Wall, since VC's /Wall is ridiculously verbose.
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3")
|
||||
# Disable VC secure checks, since these are not really issues.
|
||||
ADD_DEFINITIONS("-D_CRT_SECURE_NO_WARNINGS=1")
|
||||
ADD_DEFINITIONS("-D_SCL_SECURE_NO_WARNINGS=1")
|
||||
ADD_DEFINITIONS("-DNOGDI=1")
|
||||
ELSE()
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
|
||||
ENDIF()
|
||||
|
||||
IF(APPLE)
|
||||
# This is set to ON as of policy CMP0042
|
||||
SET(CMAKE_MACOSX_RPATH ON)
|
||||
ENDIF()
|
||||
|
||||
# Build output checks
|
||||
OPTION(LIBTINS_BUILD_SHARED "Build libtins as a shared library." ON)
|
||||
IF(LIBTINS_BUILD_SHARED)
|
||||
MESSAGE(
|
||||
STATUS
|
||||
STATUS
|
||||
"Build will generate a shared library. "
|
||||
"Use LIBTINS_BUILD_SHARED=0 to perform a static build"
|
||||
)
|
||||
@@ -24,18 +41,26 @@ IF(LIBTINS_BUILD_SHARED)
|
||||
ELSE(LIBTINS_BUILD_SHARED)
|
||||
MESSAGE(STATUS "Build will generate a static library.")
|
||||
SET(LIBTINS_TYPE STATIC)
|
||||
ADD_DEFINITIONS("-DTINS_STATIC=1")
|
||||
ENDIF(LIBTINS_BUILD_SHARED)
|
||||
|
||||
# The version number.
|
||||
SET(LIBTINS_VERSION_MAJOR 3)
|
||||
SET(LIBTINS_VERSION_MINOR 2)
|
||||
SET(LIBTINS_VERSION "${LIBTINS_VERSION_MAJOR}.${LIBTINS_VERSION_MINOR}")
|
||||
SET(TINS_VERSION_MAJOR 4)
|
||||
SET(TINS_VERSION_MINOR 4)
|
||||
SET(TINS_VERSION_PATCH 0)
|
||||
SET(LIBTINS_VERSION "${TINS_VERSION_MAJOR}.${TINS_VERSION_MINOR}")
|
||||
|
||||
# Required Packages
|
||||
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
|
||||
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/")
|
||||
|
||||
# Allow disabling packet capture mechanism
|
||||
OPTION(LIBTINS_ENABLE_PCAP "Enable capturing packets via libpcap" ON)
|
||||
|
||||
# Look for libpcap
|
||||
FIND_PACKAGE(PCAP REQUIRED)
|
||||
IF(LIBTINS_ENABLE_PCAP)
|
||||
FIND_PACKAGE(PCAP REQUIRED)
|
||||
SET(TINS_HAVE_PCAP ON)
|
||||
ENDIF()
|
||||
|
||||
# Set some Windows specific flags
|
||||
IF(WIN32)
|
||||
@@ -43,50 +68,153 @@ IF(WIN32)
|
||||
SET(LIBTINS_OS_LIBS Ws2_32.lib Iphlpapi.lib)
|
||||
|
||||
# Add the NOMINMAX macro to avoid Windows' min and max macros.
|
||||
# While compiling on windows, for some reason, WIN32 is not defined,
|
||||
# maybe we could fix this later, but it's OK for now.
|
||||
ADD_DEFINITIONS(-DNOMINMAX -DWIN32)
|
||||
ADD_DEFINITIONS(-DNOMINMAX)
|
||||
|
||||
# MinWG need some extra definitions to compile properly (WIN32 for PCAP and WIN32_WINNT version for ws2tcpip.h)
|
||||
IF(MINGW)
|
||||
ADD_DEFINITIONS(-DWIN32)
|
||||
MACRO(get_WIN32_WINNT version)
|
||||
IF (WIN32 AND CMAKE_SYSTEM_VERSION)
|
||||
SET(ver ${CMAKE_SYSTEM_VERSION})
|
||||
STRING(REPLACE "." "" ver ${ver})
|
||||
STRING(REGEX REPLACE "([0-9])" "0\\1" ver ${ver})
|
||||
SET(${version} "0x${ver}")
|
||||
ENDIF()
|
||||
ENDMACRO()
|
||||
get_WIN32_WINNT(ver)
|
||||
ADD_DEFINITIONS(-D_WIN32_WINNT=${ver})
|
||||
ENDIF(MINGW)
|
||||
|
||||
ENDIF(WIN32)
|
||||
|
||||
INCLUDE(ExternalProject)
|
||||
|
||||
# *******************
|
||||
# Compilation options
|
||||
OPTION(LIBTINS_ENABLE_CXX11 "Compile libtins with c++11 features" OFF)
|
||||
# *******************
|
||||
|
||||
# Always check for C++ features
|
||||
INCLUDE(CheckCXXFeatures)
|
||||
|
||||
IF(HAS_GCC_BUILTIN_SWAP)
|
||||
SET(TINS_HAVE_GCC_BUILTIN_SWAP ON)
|
||||
ENDIF()
|
||||
|
||||
# C++11 support
|
||||
OPTION(LIBTINS_ENABLE_CXX11 "Compile libtins with c++11 features" ON)
|
||||
IF(LIBTINS_ENABLE_CXX11)
|
||||
SET(HAVE_CXX11 ON)
|
||||
INCLUDE(CheckCXX11Features)
|
||||
IF(HAS_CXX11_NULLPTR AND HAS_CXX11_RVALUE_REFERENCES)
|
||||
# We only use declval and decltype on gcc/clang as VC fails to build that code,
|
||||
# at least on VC2013
|
||||
IF(HAS_CXX11_RVALUE_REFERENCES AND HAS_CXX11_FUNCTIONAL AND HAS_CXX11_CHRONO AND
|
||||
HAS_CXX11_NOEXCEPT AND ((HAS_CXX11_DECLVAL AND HAS_CXX11_DECLTYPE) OR MSVC))
|
||||
SET(TINS_HAVE_CXX11 ON)
|
||||
MESSAGE(STATUS "Enabling C++11 features")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX11_COMPILER_FLAGS}")
|
||||
ELSE(HAS_CXX11_NULLPTR AND HAS_CXX11_RVALUE_REFERENCES)
|
||||
MESSAGE(FATAL_ERROR "C++11 features requested but the compiler does not support them.")
|
||||
ENDIF(HAS_CXX11_NULLPTR AND HAS_CXX11_RVALUE_REFERENCES)
|
||||
ELSE()
|
||||
MESSAGE(WARNING "The compiler doesn't support the necessary C++11 features. "
|
||||
"Disabling C++11 on this build")
|
||||
ENDIF()
|
||||
ELSE(LIBTINS_ENABLE_CXX11)
|
||||
MESSAGE(
|
||||
WARNING
|
||||
WARNING
|
||||
"Disabling C++11 features. Use LIBTINS_ENABLE_CXX11=1 to enable them. "
|
||||
"Unless you are using an old compiler, you should enable this option, "
|
||||
"as it increases the library's performance")
|
||||
ENDIF(LIBTINS_ENABLE_CXX11)
|
||||
|
||||
# IEEE 802.11 and WPA2 decryption support
|
||||
OPTION(LIBTINS_ENABLE_DOT11 "Compile libtins with IEEE 802.11 support" ON)
|
||||
OPTION(LIBTINS_ENABLE_WPA2 "Compile libtins with WPA2 decryption features (requires OpenSSL)" ON)
|
||||
IF(LIBTINS_ENABLE_DOT11)
|
||||
SET(HAVE_DOT11 ON)
|
||||
SET(TINS_HAVE_DOT11 ON)
|
||||
MESSAGE(STATUS "Enabling IEEE 802.11 support.")
|
||||
IF(LIBTINS_ENABLE_WPA2)
|
||||
FIND_PACKAGE(OpenSSL REQUIRED)
|
||||
SET(HAVE_WPA2_DECRYPTION ON)
|
||||
MESSAGE(STATUS "Enabling WPA2 decryption support.")
|
||||
FIND_PACKAGE(OpenSSL)
|
||||
IF(OPENSSL_FOUND)
|
||||
SET(TINS_HAVE_WPA2_DECRYPTION ON)
|
||||
MESSAGE(STATUS "Enabling WPA2 decryption support.")
|
||||
ELSE()
|
||||
MESSAGE(WARNING "Disabling WPA2 decryption support since OpenSSL was not found")
|
||||
# Default this to empty strings
|
||||
SET(OPENSSL_INCLUDE_DIR "")
|
||||
SET(OPENSSL_LIBRARIES "")
|
||||
ENDIF()
|
||||
ELSE(LIBTINS_ENABLE_WPA2)
|
||||
MESSAGE(STATUS "Disabling WPA2 decryption support.")
|
||||
ENDIF(LIBTINS_ENABLE_WPA2)
|
||||
ENDIF(LIBTINS_ENABLE_DOT11)
|
||||
|
||||
# Optionally enable TCPIP classes (on by default)
|
||||
OPTION(LIBTINS_ENABLE_TCPIP "Enable TCPIP classes" ON)
|
||||
IF(LIBTINS_ENABLE_TCPIP AND TINS_HAVE_CXX11)
|
||||
SET(TINS_HAVE_TCPIP ON)
|
||||
MESSAGE(STATUS "Enabling TCPIP classes")
|
||||
ELSE()
|
||||
SET(TINS_HAVE_TCPIP OFF)
|
||||
MESSAGE(STATUS "Disabling TCPIP classes")
|
||||
ENDIF()
|
||||
|
||||
# Search for libboost
|
||||
FIND_PACKAGE(Boost)
|
||||
|
||||
# Optionally enable the ACK tracker (on by default)
|
||||
OPTION(LIBTINS_ENABLE_ACK_TRACKER "Enable TCP ACK tracking support" ON)
|
||||
IF(LIBTINS_ENABLE_ACK_TRACKER AND TINS_HAVE_CXX11)
|
||||
IF (Boost_FOUND)
|
||||
MESSAGE(STATUS "Enabling TCP ACK tracking support.")
|
||||
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
|
||||
SET(TINS_HAVE_ACK_TRACKER ON)
|
||||
ELSE()
|
||||
MESSAGE(WARNING "Disabling ACK tracking support as boost.icl was not found")
|
||||
SET(TINS_HAVE_ACK_TRACKER OFF)
|
||||
ENDIF()
|
||||
ELSE()
|
||||
SET(TINS_HAVE_ACK_TRACKER OFF)
|
||||
MESSAGE(STATUS "Disabling ACK tracking support")
|
||||
ENDIF()
|
||||
|
||||
# Optionally enable the TCP stream custom data (on by default)
|
||||
OPTION(LIBTINS_ENABLE_TCP_STREAM_CUSTOM_DATA "Enable TCP stream custom data support" ON)
|
||||
IF(LIBTINS_ENABLE_TCP_STREAM_CUSTOM_DATA AND TINS_HAVE_CXX11)
|
||||
IF (Boost_FOUND)
|
||||
MESSAGE(STATUS "Enabling TCP stream custom data support.")
|
||||
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
|
||||
SET(TINS_HAVE_TCP_STREAM_CUSTOM_DATA ON)
|
||||
ELSE()
|
||||
MESSAGE(WARNING "Disabling TCP stream custom data support as boost.any was not found")
|
||||
SET(TINS_HAVE_TCP_STREAM_CUSTOM_DATA OFF)
|
||||
ENDIF()
|
||||
ELSE()
|
||||
SET(TINS_HAVE_TCP_STREAM_CUSTOM_DATA OFF)
|
||||
MESSAGE(STATUS "Disabling TCP stream custom data support")
|
||||
ENDIF()
|
||||
|
||||
OPTION(LIBTINS_ENABLE_WPA2_CALLBACKS "Enable WPA2 callback interface" ON)
|
||||
IF(LIBTINS_ENABLE_WPA2_CALLBACKS AND TINS_HAVE_WPA2_DECRYPTION AND TINS_HAVE_CXX11)
|
||||
SET(STATUS "Enabling WPA2 callback interface")
|
||||
SET(TINS_HAVE_WPA2_CALLBACKS ON)
|
||||
ENDIF()
|
||||
|
||||
# Use pcap_sendpacket to send l2 packets rather than raw sockets
|
||||
IF(WIN32)
|
||||
SET(USE_PCAP_SENDPACKET_DEFAULT ON)
|
||||
ELSE(WIN32)
|
||||
SET(USE_PCAP_SENDPACKET_DEFAULT OFF)
|
||||
ENDIF(WIN32)
|
||||
|
||||
OPTION(LIBTINS_USE_PCAP_SENDPACKET "Use pcap_sendpacket to send l2 packets"
|
||||
${USE_PCAP_SENDPACKET_DEFAULT})
|
||||
IF(LIBTINS_ENABLE_PCAP AND LIBTINS_USE_PCAP_SENDPACKET)
|
||||
SET(TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET ON)
|
||||
MESSAGE(STATUS "Using pcap_sendpacket to send l2 packets.")
|
||||
ENDIF()
|
||||
|
||||
# Add a target to generate API documentation using Doxygen
|
||||
FIND_PACKAGE(Doxygen QUIET)
|
||||
IF(DOXYGEN_FOUND)
|
||||
CONFIGURE_FILE(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
|
||||
@ONLY
|
||||
)
|
||||
ADD_CUSTOM_TARGET(
|
||||
@@ -97,35 +225,97 @@ IF(DOXYGEN_FOUND)
|
||||
)
|
||||
ENDIF(DOXYGEN_FOUND)
|
||||
|
||||
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
|
||||
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
|
||||
|
||||
# Configuration file
|
||||
CONFIGURE_FILE(
|
||||
"${PROJECT_SOURCE_DIR}/include/tins/config.h.in"
|
||||
"${PROJECT_SOURCE_DIR}/include/tins/config.h"
|
||||
)
|
||||
|
||||
IF (NOT CMAKE_INSTALL_LIBDIR)
|
||||
SET(CMAKE_INSTALL_LIBDIR lib)
|
||||
ENDIF()
|
||||
IF (NOT CMAKE_INSTALL_BINDIR)
|
||||
SET(CMAKE_INSTALL_BINDIR bin)
|
||||
ENDIF()
|
||||
# The library output directory
|
||||
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
|
||||
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
|
||||
# Support for pkg-config
|
||||
set(CMAKE_INSTALL_LIBDIR lib)
|
||||
set(pkgconfig_prefix ${CMAKE_INSTALL_PREFIX})
|
||||
set(pkgconfig_exec_prefix ${CMAKE_INSTALL_PREFIX})
|
||||
set(pkgconfig_libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
|
||||
set(pkgconfig_version ${LIBTINS_VERSION})
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libtins.pc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libtins.pc @ONLY)
|
||||
SET(pkgconfig_prefix ${CMAKE_INSTALL_PREFIX})
|
||||
SET(pkgconfig_exec_prefix ${CMAKE_INSTALL_PREFIX})
|
||||
SET(pkgconfig_libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
|
||||
SET(pkgconfig_version ${LIBTINS_VERSION})
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libtins.pc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libtins.pc @ONLY)
|
||||
|
||||
install(
|
||||
INSTALL(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libtins.pc
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
|
||||
)
|
||||
|
||||
ENABLE_TESTING()
|
||||
ADD_SUBDIRECTORY(include)
|
||||
# Confiugure the uninstall script
|
||||
CONFIGURE_FILE(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
||||
IMMEDIATE @ONLY
|
||||
)
|
||||
|
||||
# Add uninstall target
|
||||
ADD_CUSTOM_TARGET(uninstall
|
||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
|
||||
|
||||
# ******************
|
||||
# Add subdirectories
|
||||
# ******************
|
||||
ADD_SUBDIRECTORY(src)
|
||||
ADD_SUBDIRECTORY(tests)
|
||||
ADD_SUBDIRECTORY(examples)
|
||||
|
||||
IF(LIBTINS_BUILD_EXAMPLES)
|
||||
IF(LIBTINS_ENABLE_PCAP)
|
||||
ADD_SUBDIRECTORY(examples)
|
||||
ELSE()
|
||||
MESSAGE(STATUS "Not building examples as pcap support is disabled")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
IF(LIBTINS_BUILD_TESTS)
|
||||
# Only include googletest if the git submodule has been fetched
|
||||
IF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/googletest/CMakeLists.txt")
|
||||
# Enable tests and add the test directory
|
||||
MESSAGE(STATUS "Tests have been enabled")
|
||||
SET(GOOGLETEST_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/googletest)
|
||||
SET(GOOGLETEST_INCLUDE ${GOOGLETEST_ROOT}/googletest/include)
|
||||
SET(GOOGLETEST_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/googletest)
|
||||
SET(GOOGLETEST_LIBRARY ${GOOGLETEST_BINARY_DIR}/googletest)
|
||||
|
||||
ExternalProject_Add(
|
||||
googletest
|
||||
DOWNLOAD_COMMAND ""
|
||||
SOURCE_DIR ${GOOGLETEST_ROOT}
|
||||
BINARY_DIR ${GOOGLETEST_BINARY_DIR}
|
||||
CMAKE_CACHE_ARGS "-DBUILD_GTEST:bool=ON" "-DBUILD_GMOCK:bool=OFF"
|
||||
"-Dgtest_force_shared_crt:bool=ON"
|
||||
"-DCMAKE_CXX_COMPILER:path=${CMAKE_CXX_COMPILER}"
|
||||
INSTALL_COMMAND ""
|
||||
)
|
||||
# Make sure we build googletest before anything else
|
||||
ADD_DEPENDENCIES(tins googletest)
|
||||
ENABLE_TESTING()
|
||||
ADD_SUBDIRECTORY(tests)
|
||||
ELSE()
|
||||
MESSAGE(STATUS "googletest git submodule is absent. Run `git submodule init && git submodule update` to get it")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
# **********************************
|
||||
# CMake project configuration export
|
||||
# **********************************
|
||||
|
||||
if(UNIX)
|
||||
set(CONF_CMAKE_INSTALL_DIR lib/cmake/libtins)
|
||||
else()
|
||||
set(CONF_CMAKE_INSTALL_DIR CMake)
|
||||
endif()
|
||||
|
||||
# Add all targets to the build-tree export set
|
||||
EXPORT(
|
||||
@@ -153,13 +343,13 @@ INSTALL(
|
||||
FILES
|
||||
"${PROJECT_BINARY_DIR}/libtinsConfig.cmake"
|
||||
"${PROJECT_BINARY_DIR}/libtinsConfigVersion.cmake"
|
||||
DESTINATION CMake
|
||||
DESTINATION ${CONF_CMAKE_INSTALL_DIR}
|
||||
COMPONENT dev
|
||||
)
|
||||
|
||||
# Install the export set for use with the install-tree
|
||||
INSTALL(
|
||||
EXPORT libtinsTargets
|
||||
DESTINATION CMake
|
||||
DESTINATION ${CONF_CMAKE_INSTALL_DIR}
|
||||
COMPONENT dev
|
||||
)
|
||||
|
||||
27
CONTRIBUTING.md
Normal file
27
CONTRIBUTING.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Contributing
|
||||
|
||||
Bug reports and enhancements to the library are really valued and appreciated!
|
||||
|
||||
# Bug reports
|
||||
|
||||
If you find a bug, please report it! Bugs on the library are taken seriously
|
||||
and a patch for them is usually pushed on the same day.
|
||||
|
||||
When reporting a bug, please make sure to indicate the platform (e.g. GNU/Linux, Windows, OSX)
|
||||
in which you came across the issue, as this is essential to finding the cause.
|
||||
|
||||
## Packet parsing bugs
|
||||
|
||||
If you find a bug related to packet parsing (e.g. a field on a packet contains an
|
||||
invalid value), please try to provide a pcap file that contains the packet that
|
||||
was incorrectly parsed. Doing this will make it very simple to find the issue, plus
|
||||
you will be asked to provide this file anyway, so this just makes things
|
||||
easier.
|
||||
|
||||
# Pull requests
|
||||
|
||||
Pull requests are very welcomed. When doing a pull request please:
|
||||
|
||||
* Notice that your code will be compiled and tests will be run automatically by the travis and
|
||||
appveyor CI tools. If your code has issues on any of the tested platforms (GNU/Linux, Windows
|
||||
and OSX), please fix it or otherwise the PR won't be merged.
|
||||
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2012-2014, Matias Fontanini
|
||||
Copyright (c) 2012-2017, Matias Fontanini
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
||||
60
README.md
60
README.md
@@ -1,5 +1,7 @@
|
||||
libtins
|
||||
=======
|
||||
# libtins
|
||||
|
||||
[](https://travis-ci.org/mfontanini/libtins)
|
||||
[](https://ci.appveyor.com/project/mfontanini/libtins/branch/master)
|
||||
|
||||
libtins is a high-level, multiplatform C++ network packet sniffing and
|
||||
crafting library.
|
||||
@@ -34,6 +36,7 @@ cmake ../
|
||||
make
|
||||
```
|
||||
|
||||
### Static/shared build
|
||||
Note that by default, only the shared object is compiled. If you would
|
||||
like to generate a static library file, run:
|
||||
|
||||
@@ -44,7 +47,9 @@ cmake ../ -DLIBTINS_BUILD_SHARED=0
|
||||
The generated static/shared library files will be located in the
|
||||
_build/lib_ directory.
|
||||
|
||||
libtins is noticeable faster if you enable _C++11_ support. Therefore,
|
||||
### C++11 support
|
||||
|
||||
libtins is noticeably faster if you enable _C++11_ support. Therefore,
|
||||
if your compiler supports this standard, then you should enable it.
|
||||
In order to do so, use the _LIBTINS_ENABLE_CXX11_ switch:
|
||||
|
||||
@@ -52,6 +57,22 @@ In order to do so, use the _LIBTINS_ENABLE_CXX11_ switch:
|
||||
cmake ../ -DLIBTINS_ENABLE_CXX11=1
|
||||
```
|
||||
|
||||
### TCP ACK tracker
|
||||
|
||||
The TCP ACK tracker feature requires the boost.icl library (header only).
|
||||
This feature is enabled by default but will be disabled if the boost
|
||||
headers are not found. You can disable this feature by using:
|
||||
|
||||
```Shell
|
||||
cmake ../ -DLIBTINS_ENABLE_ACK_TRACKER=0
|
||||
```
|
||||
|
||||
If your boost installation is on some non-standard path, use
|
||||
the parameters shown on the
|
||||
[CMake FindBoost help](https://cmake.org/cmake/help/v3.0/module/FindBoost.html)
|
||||
|
||||
### WPA2 decryption
|
||||
|
||||
If you want to disable _WPA2_ decryption support, which will remove
|
||||
openssl as a dependency for compilation, use the
|
||||
_LIBTINS_ENABLE_WPA2_ switch:
|
||||
@@ -60,6 +81,8 @@ _LIBTINS_ENABLE_WPA2_ switch:
|
||||
cmake ../ -DLIBTINS_ENABLE_WPA2=0
|
||||
```
|
||||
|
||||
### IEEE 802.11 support
|
||||
|
||||
If you want to disable IEEE 802.11 support(this will also disable
|
||||
RadioTap and WPA2 decryption), which will reduce the size of the
|
||||
resulting library in around 20%, use the _LIBTINS_ENABLE_DOT11_ switch:
|
||||
@@ -85,9 +108,40 @@ in order to invalidate it, you should run(as root):
|
||||
ldconfig
|
||||
```
|
||||
|
||||
## Running tests ##
|
||||
|
||||
You may want to run the unit tests on your system so you make sure
|
||||
everything works. In order to do so, you need to follow these steps:
|
||||
|
||||
```Shell
|
||||
# This will fetch the googletest submodule, needed for tests
|
||||
git submodule init
|
||||
git submodule update
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
# Use any options you want
|
||||
cmake ..
|
||||
|
||||
# Compile tests
|
||||
make tests
|
||||
|
||||
# Run them
|
||||
make test
|
||||
```
|
||||
|
||||
If you find that any tests fail, please create an ticket in the
|
||||
issue tracker indicating the platform and architecture you're using.
|
||||
|
||||
## Examples ##
|
||||
|
||||
You might want to have a look at the examples located in the "examples"
|
||||
directory. The same samples can be found online at:
|
||||
|
||||
http://libtins.github.io/examples/
|
||||
|
||||
## Contributing ##
|
||||
|
||||
If you want to report a bug or make a pull request, please have a look at
|
||||
the [contributing](CONTRIBUTING.md) file before doing so.
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
# HAS_CXX11_CONSTEXPR - constexpr keyword
|
||||
# HAS_CXX11_CSTDINT_H - cstdint header
|
||||
# HAS_CXX11_DECLTYPE - decltype keyword
|
||||
# HAS_CXX11_DECLVAL - declval feature
|
||||
# HAS_CXX11_FUNC - __func__ preprocessor constant
|
||||
# HAS_CXX11_INITIALIZER_LIST - initializer list
|
||||
# HAS_CXX11_LAMBDA - lambdas
|
||||
@@ -68,24 +69,24 @@ endif ()
|
||||
|
||||
function(cxx11_check_feature FEATURE_NAME RESULT_VAR)
|
||||
if (NOT DEFINED ${RESULT_VAR})
|
||||
set(_bindir "${CMAKE_CURRENT_BINARY_DIR}/cxx11_${FEATURE_NAME}")
|
||||
set(_bindir "${CMAKE_CURRENT_BINARY_DIR}/cxx_${FEATURE_NAME}")
|
||||
|
||||
set(_SRCFILE_BASE ${CMAKE_CURRENT_LIST_DIR}/CheckCXX11Features/cxx11-test-${FEATURE_NAME})
|
||||
set(_SRCFILE_BASE ${CMAKE_CURRENT_LIST_DIR}/CheckCXXFeatures/cxx-test-${FEATURE_NAME})
|
||||
set(_LOG_NAME "\"${FEATURE_NAME}\"")
|
||||
message(STATUS "Checking C++11 support for ${_LOG_NAME}")
|
||||
message(STATUS "Checking C++ support for ${_LOG_NAME}")
|
||||
|
||||
set(_SRCFILE "${_SRCFILE_BASE}.cpp")
|
||||
set(_SRCFILE_FAIL "${_SRCFILE_BASE}_fail.cpp")
|
||||
set(_SRCFILE_FAIL_COMPILE "${_SRCFILE_BASE}_fail_compile.cpp")
|
||||
|
||||
if (CROSS_COMPILING)
|
||||
if (CMAKE_CROSSCOMPILING)
|
||||
try_compile(${RESULT_VAR} "${_bindir}" "${_SRCFILE}"
|
||||
COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}")
|
||||
if (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
try_compile(${RESULT_VAR} "${_bindir}_fail" "${_SRCFILE_FAIL}"
|
||||
COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}")
|
||||
endif (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
else (CROSS_COMPILING)
|
||||
else (CMAKE_CROSSCOMPILING)
|
||||
try_run(_RUN_RESULT_VAR _COMPILE_RESULT_VAR
|
||||
"${_bindir}" "${_SRCFILE}"
|
||||
COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}")
|
||||
@@ -104,7 +105,7 @@ function(cxx11_check_feature FEATURE_NAME RESULT_VAR)
|
||||
set(${RESULT_VAR} FALSE)
|
||||
endif (_COMPILE_RESULT_VAR AND _RUN_RESULT_VAR)
|
||||
endif (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL})
|
||||
endif (CROSS_COMPILING)
|
||||
endif (CMAKE_CROSSCOMPILING)
|
||||
if (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE})
|
||||
try_compile(_TMP_RESULT "${_bindir}_fail_compile" "${_SRCFILE_FAIL_COMPILE}"
|
||||
COMPILE_DEFINITIONS "${CXX11_COMPILER_FLAGS}")
|
||||
@@ -116,27 +117,19 @@ function(cxx11_check_feature FEATURE_NAME RESULT_VAR)
|
||||
endif (${RESULT_VAR} AND EXISTS ${_SRCFILE_FAIL_COMPILE})
|
||||
|
||||
if (${RESULT_VAR})
|
||||
message(STATUS "Checking C++11 support for ${_LOG_NAME}: works")
|
||||
message(STATUS "Checking C++ support for ${_LOG_NAME}: works")
|
||||
else (${RESULT_VAR})
|
||||
message(STATUS "Checking C++11 support for ${_LOG_NAME}: not supported")
|
||||
message(STATUS "Checking C++ support for ${_LOG_NAME}: not supported")
|
||||
endif (${RESULT_VAR})
|
||||
set(${RESULT_VAR} ${${RESULT_VAR}} CACHE INTERNAL "C++11 support for ${_LOG_NAME}")
|
||||
set(${RESULT_VAR} ${${RESULT_VAR}} CACHE INTERNAL "C++ support for ${_LOG_NAME}")
|
||||
endif (NOT DEFINED ${RESULT_VAR})
|
||||
endfunction(cxx11_check_feature)
|
||||
|
||||
cxx11_check_feature("__func__" HAS_CXX11_FUNC)
|
||||
cxx11_check_feature("auto" HAS_CXX11_AUTO)
|
||||
cxx11_check_feature("auto_ret_type" HAS_CXX11_AUTO_RET_TYPE)
|
||||
cxx11_check_feature("class_override_final" HAS_CXX11_CLASS_OVERRIDE)
|
||||
cxx11_check_feature("constexpr" HAS_CXX11_CONSTEXPR)
|
||||
cxx11_check_feature("cstdint" HAS_CXX11_CSTDINT_H)
|
||||
cxx11_check_feature("decltype" HAS_CXX11_DECLTYPE)
|
||||
cxx11_check_feature("declval" HAS_CXX11_DECLVAL)
|
||||
cxx11_check_feature("initializer_list" HAS_CXX11_INITIALIZER_LIST)
|
||||
cxx11_check_feature("lambda" HAS_CXX11_LAMBDA)
|
||||
cxx11_check_feature("long_long" HAS_CXX11_LONG_LONG)
|
||||
cxx11_check_feature("nullptr" HAS_CXX11_NULLPTR)
|
||||
cxx11_check_feature("regex" HAS_CXX11_LIB_REGEX)
|
||||
cxx11_check_feature("rvalue-references" HAS_CXX11_RVALUE_REFERENCES)
|
||||
cxx11_check_feature("sizeof_member" HAS_CXX11_SIZEOF_MEMBER)
|
||||
cxx11_check_feature("static_assert" HAS_CXX11_STATIC_ASSERT)
|
||||
cxx11_check_feature("variadic_templates" HAS_CXX11_VARIADIC_TEMPLATES)
|
||||
cxx11_check_feature("functional" HAS_CXX11_FUNCTIONAL)
|
||||
cxx11_check_feature("chrono" HAS_CXX11_CHRONO)
|
||||
cxx11_check_feature("noexcept" HAS_CXX11_NOEXCEPT)
|
||||
cxx11_check_feature("builtin-swap" HAS_GCC_BUILTIN_SWAP)
|
||||
8
cmake/Modules/CheckCXXFeatures/cxx-test-builtin-swap.cpp
Normal file
8
cmake/Modules/CheckCXXFeatures/cxx-test-builtin-swap.cpp
Normal file
@@ -0,0 +1,8 @@
|
||||
#include <stdint.h>
|
||||
|
||||
int main() {
|
||||
uint16_t u16 = __builtin_bswap16(0x9812U);
|
||||
uint32_t u32 = __builtin_bswap32(0x9812ad81U);
|
||||
uint64_t u64 = __builtin_bswap64(0x9812ad81f61a890dU);
|
||||
return (u16 > 0 && u32 > 0 && u64 > 0) ? 0 : 1;
|
||||
}
|
||||
9
cmake/Modules/CheckCXXFeatures/cxx-test-chrono.cpp
Normal file
9
cmake/Modules/CheckCXXFeatures/cxx-test-chrono.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#include <chrono>
|
||||
|
||||
using namespace std::chrono;
|
||||
|
||||
int main() {
|
||||
system_clock::time_point tp = system_clock::now();
|
||||
milliseconds ms = duration_cast<milliseconds>(tp.time_since_epoch());
|
||||
return (ms.count() > 0) ? 0 : 1;
|
||||
}
|
||||
19
cmake/Modules/CheckCXXFeatures/cxx-test-declval.cpp
Normal file
19
cmake/Modules/CheckCXXFeatures/cxx-test-declval.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
// Example code taken from http://en.cppreference.com/w/cpp/utility/declval
|
||||
|
||||
#include <utility>
|
||||
#include <iostream>
|
||||
|
||||
struct Default { int foo() const { return 1; } };
|
||||
|
||||
struct NonDefault
|
||||
{
|
||||
NonDefault(const NonDefault&) { }
|
||||
int foo() const { return 1; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
decltype(Default().foo()) n1 = 1; // type of n1 is int
|
||||
decltype(std::declval<NonDefault>().foo()) n2 = n1; // type of n2 is int
|
||||
return (n1 == 1 && n2 == 1) ? 0 : 1;
|
||||
}
|
||||
11
cmake/Modules/CheckCXXFeatures/cxx-test-functional.cpp
Normal file
11
cmake/Modules/CheckCXXFeatures/cxx-test-functional.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#include <functional>
|
||||
|
||||
int add(int x, int y) {
|
||||
return x + y;
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::function<int(int, int)> func;
|
||||
func = std::bind(&add, std::placeholders::_1, std::placeholders::_2);
|
||||
return (func(2, 2) == 4) ? 0 : 1;
|
||||
}
|
||||
7
cmake/Modules/CheckCXXFeatures/cxx-test-noexcept.cpp
Normal file
7
cmake/Modules/CheckCXXFeatures/cxx-test-noexcept.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
int foo() noexcept {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
return foo();
|
||||
}
|
||||
@@ -18,6 +18,7 @@
|
||||
# PCAP_LIBRARY The libpcap library (possibly includes a thread
|
||||
# library e.g. required by pf_ring's libpcap)
|
||||
# HAVE_PF_RING If a found version of libpcap supports PF_RING
|
||||
# HAVE_PCAP_IMMEDIATE_MODE If the version of libpcap found supports immediate mode
|
||||
|
||||
find_path(PCAP_ROOT_DIR
|
||||
NAMES include/pcap.h
|
||||
@@ -28,9 +29,17 @@ find_path(PCAP_INCLUDE_DIR
|
||||
HINTS ${PCAP_ROOT_DIR}/include
|
||||
)
|
||||
|
||||
set (HINT_DIR ${PCAP_ROOT_DIR}/lib)
|
||||
|
||||
# On x64 windows, we should look also for the .lib at /lib/x64/
|
||||
# as this is the default path for the WinPcap developer's pack
|
||||
if (${CMAKE_SIZEOF_VOID_P} EQUAL 8 AND WIN32)
|
||||
set (HINT_DIR ${PCAP_ROOT_DIR}/lib/x64/ ${HINT_DIR})
|
||||
endif ()
|
||||
|
||||
find_library(PCAP_LIBRARY
|
||||
NAMES pcap wpcap
|
||||
HINTS ${PCAP_ROOT_DIR}/lib
|
||||
HINTS ${HINT_DIR}
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
@@ -65,6 +74,8 @@ endif (NOT PCAP_LINKS_SOLO)
|
||||
include(CheckFunctionExists)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY})
|
||||
check_function_exists(pcap_get_pfring_id HAVE_PF_RING)
|
||||
check_function_exists(pcap_set_immediate_mode HAVE_PCAP_IMMEDIATE_MODE)
|
||||
check_function_exists(pcap_set_tstamp_precision HAVE_PCAP_TIMESTAMP_PRECISION)
|
||||
set(CMAKE_REQUIRED_LIBRARIES)
|
||||
|
||||
mark_as_advanced(
|
||||
|
||||
53
cmake/appveyor.yml
Normal file
53
cmake/appveyor.yml
Normal file
@@ -0,0 +1,53 @@
|
||||
version: 1.0.{build}
|
||||
configuration:
|
||||
- debug
|
||||
- release
|
||||
platform:
|
||||
- Win32
|
||||
- x64
|
||||
environment:
|
||||
matrix:
|
||||
- compiler: vs2013
|
||||
- compiler: vs2015
|
||||
BOOST_ROOT: C:/Libraries/boost
|
||||
clone_depth: 1
|
||||
install:
|
||||
- git clone https://github.com/mfontanini/winpcap-installer.git
|
||||
- cd winpcap-installer
|
||||
- winpcap-boundary-meter-4.1.3.exe /S
|
||||
- cd ..
|
||||
- appveyor DownloadFile http://www.winpcap.org/install/bin/WpdPack_4_1_2.zip
|
||||
- 7z x .\WpdPack_4_1_2.zip -oc:\
|
||||
- git submodule init
|
||||
- git submodule update
|
||||
before_build:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- if "%compiler%"=="vs2013" (set VS_VERSION=12) else (set VS_VERSION=14)
|
||||
- set VS=Visual Studio %VS_VERSION%
|
||||
- if "%platform%"=="Win32" (set GENERATOR="%VS%" & set ARCH_BITS=32)
|
||||
- if "%platform%"=="x64" (set GENERATOR="%VS% Win64" & set ARCH_BITS=64)
|
||||
- set BOOST_LIBRARYDIR=C:\Libraries\boost\lib%ARCH_BITS%-msvc-%VS_VERSION%.0
|
||||
- cmake .. -G %GENERATOR% -DPCAP_ROOT_DIR=c:\WpdPack -DLIBTINS_BUILD_SHARED=0 -DLIBTINS_ENABLE_WPA2=0 -DBOOST_ROOT="%BOOST_ROOT%" -DBOOST_LIBRARYDIR="%BOOST_LIBRARYDIR%" -DBoost_USE_STATIC_LIBS="ON"
|
||||
build:
|
||||
project: C:/projects/libtins/build/libtins.sln
|
||||
verbosity: minimal
|
||||
after_build:
|
||||
- mkdir install\libtins\include
|
||||
- mkdir install\libtins\lib
|
||||
- cd install\libtins
|
||||
- copy C:\projects\libtins\build\lib\%Configuration%\tins.lib lib
|
||||
- xcopy C:\projects\libtins\include include /s /e
|
||||
- del include\CMakeLists.txt
|
||||
- del include\tins\CMakeLists.txt
|
||||
- del include\tins\config.h.in
|
||||
- del include\tins\dot11\CMakeLists.txt
|
||||
- cd ..\
|
||||
- 7z a libtins-%compiler%-%platform%-%Configuration%.zip libtins
|
||||
test_script:
|
||||
- cd c:\projects\libtins\build
|
||||
- ctest -C %Configuration% -V
|
||||
deploy_script:
|
||||
- ps: Push-AppveyorArtifact "install\libtins-$env:Compiler-$env:Platform-$env:Configuration.zip"
|
||||
skip_commits:
|
||||
message: /Update documentation.*/
|
||||
23
cmake/cmake_uninstall.cmake.in
Normal file
23
cmake/cmake_uninstall.cmake.in
Normal file
@@ -0,0 +1,23 @@
|
||||
# Taken from https://cmake.org/Wiki/CMake_FAQ#Can_I_do_.22make_uninstall.22_with_CMake.3F
|
||||
|
||||
if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||
endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||
|
||||
file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
|
||||
string(REGEX REPLACE "\n" ";" files "${files}")
|
||||
foreach(file ${files})
|
||||
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
|
||||
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||
exec_program(
|
||||
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
|
||||
OUTPUT_VARIABLE rm_out
|
||||
RETURN_VALUE rm_retval
|
||||
)
|
||||
if(NOT "${rm_retval}" STREQUAL 0)
|
||||
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
|
||||
endif(NOT "${rm_retval}" STREQUAL 0)
|
||||
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
|
||||
endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||
endforeach(file)
|
||||
@@ -1365,7 +1365,9 @@ INCLUDE_FILE_PATTERNS =
|
||||
# undefined via #undef or recursively expanded use the := operator
|
||||
# instead of the = operator.
|
||||
|
||||
PREDEFINED =
|
||||
PREDEFINED = "TINS_IS_CXX11=1" \
|
||||
"TINS_HAVE_WPA2_CALLBACKS=1" \
|
||||
"TINS_HAVE_DOT11=1"
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
|
||||
# this tag can be used to specify a list of macro names that should be expanded.
|
||||
|
||||
@@ -1,58 +1,81 @@
|
||||
FIND_PACKAGE(libtins QUIET)
|
||||
FIND_PACKAGE(Threads QUIET)
|
||||
FIND_PACKAGE(Boost COMPONENTS regex)
|
||||
|
||||
IF(libtins_FOUND)
|
||||
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/examples)
|
||||
INCLUDE_DIRECTORIES(${LIBTINS_INCLUDE_DIRS})
|
||||
LINK_LIBRARIES(${LIBTINS_LIBRARIES})
|
||||
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/examples)
|
||||
INCLUDE_DIRECTORIES(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../include
|
||||
${PCAP_INCLUDE_DIR}
|
||||
)
|
||||
LINK_LIBRARIES(tins)
|
||||
|
||||
IF(HAVE_CXX11)
|
||||
SET(LIBTINS_CXX11_EXAMPLES
|
||||
arpmonitor
|
||||
dns_queries
|
||||
dns_spoof
|
||||
dns_stats
|
||||
wps_detect
|
||||
traceroute
|
||||
)
|
||||
ELSE(HAVE_CXX11)
|
||||
MESSAGE(WARNING "Disabling some examples since C++11 support is disabled.")
|
||||
ENDIF(HAVE_CXX11)
|
||||
|
||||
ADD_CUSTOM_TARGET(
|
||||
examples DEPENDS
|
||||
arpspoofing
|
||||
${LIBTINS_CXX11_EXAMPLES}
|
||||
beacon_display
|
||||
portscan
|
||||
IF(TINS_HAVE_CXX11)
|
||||
SET(LIBTINS_CXX11_EXAMPLES
|
||||
arpmonitor
|
||||
dns_queries
|
||||
dns_spoof
|
||||
dns_stats
|
||||
stream_dump
|
||||
icmp_responses
|
||||
interfaces_info
|
||||
tcp_connection_close
|
||||
traceroute
|
||||
wps_detect
|
||||
)
|
||||
IF(Boost_REGEX_FOUND)
|
||||
SET(LIBTINS_CXX11_EXAMPLES ${LIBTINS_CXX11_EXAMPLES} http_requests)
|
||||
ELSE()
|
||||
MESSAGE(WARNING "Disabling HTTP requests example since boost.regex was not found")
|
||||
ENDIF()
|
||||
ELSE(TINS_HAVE_CXX11)
|
||||
MESSAGE(WARNING "Disabling some examples since C++11 support is disabled.")
|
||||
ENDIF(TINS_HAVE_CXX11)
|
||||
|
||||
ADD_EXECUTABLE(arpspoofing EXCLUDE_FROM_ALL arpspoofing.cpp)
|
||||
IF(HAVE_CXX11)
|
||||
ADD_EXECUTABLE(arpmonitor EXCLUDE_FROM_ALL arpmonitor.cpp)
|
||||
ADD_EXECUTABLE(dns_queries EXCLUDE_FROM_ALL dns_queries.cpp)
|
||||
ADD_EXECUTABLE(dns_spoof EXCLUDE_FROM_ALL dns_spoof.cpp)
|
||||
ADD_CUSTOM_TARGET(
|
||||
examples DEPENDS
|
||||
arpspoofing
|
||||
${LIBTINS_CXX11_EXAMPLES}
|
||||
beacon_display
|
||||
portscan
|
||||
route_table
|
||||
defragmenter
|
||||
)
|
||||
|
||||
# Make sure we first build libtins
|
||||
ADD_DEPENDENCIES(examples tins)
|
||||
|
||||
ADD_EXECUTABLE(arpspoofing EXCLUDE_FROM_ALL arpspoofing.cpp)
|
||||
ADD_EXECUTABLE(route_table EXCLUDE_FROM_ALL route_table.cpp)
|
||||
ADD_EXECUTABLE(defragmenter EXCLUDE_FROM_ALL defragmenter.cpp)
|
||||
IF(TINS_HAVE_CXX11)
|
||||
ADD_EXECUTABLE(arpmonitor EXCLUDE_FROM_ALL arpmonitor.cpp)
|
||||
ADD_EXECUTABLE(dns_queries EXCLUDE_FROM_ALL dns_queries.cpp)
|
||||
ADD_EXECUTABLE(dns_spoof EXCLUDE_FROM_ALL dns_spoof.cpp)
|
||||
ADD_EXECUTABLE(stream_dump EXCLUDE_FROM_ALL stream_dump.cpp)
|
||||
ADD_EXECUTABLE(icmp_responses EXCLUDE_FROM_ALL icmp_responses.cpp)
|
||||
ADD_EXECUTABLE(interfaces_info EXCLUDE_FROM_ALL interfaces_info.cpp)
|
||||
ADD_EXECUTABLE(tcp_connection_close EXCLUDE_FROM_ALL tcp_connection_close.cpp)
|
||||
ADD_EXECUTABLE(wps_detect EXCLUDE_FROM_ALL wps_detect.cpp)
|
||||
IF (Boost_REGEX_FOUND)
|
||||
ADD_EXECUTABLE(http_requests EXCLUDE_FROM_ALL http_requests.cpp)
|
||||
TARGET_LINK_LIBRARIES(http_requests ${Boost_LIBRARIES})
|
||||
ENDIF()
|
||||
ENDIF(TINS_HAVE_CXX11)
|
||||
|
||||
ADD_EXECUTABLE(beacon_display EXCLUDE_FROM_ALL beacon_display.cpp)
|
||||
|
||||
if(THREADS_FOUND)
|
||||
IF(TINS_HAVE_CXX11)
|
||||
ADD_EXECUTABLE(traceroute EXCLUDE_FROM_ALL traceroute.cpp)
|
||||
ADD_EXECUTABLE(dns_stats EXCLUDE_FROM_ALL dns_stats.cpp)
|
||||
ADD_EXECUTABLE(wps_detect EXCLUDE_FROM_ALL wps_detect.cpp)
|
||||
ENDIF(HAVE_CXX11)
|
||||
|
||||
ADD_EXECUTABLE(beacon_display EXCLUDE_FROM_ALL beacon_display.cpp)
|
||||
|
||||
if(THREADS_FOUND)
|
||||
IF(HAVE_CXX11)
|
||||
ADD_EXECUTABLE(traceroute EXCLUDE_FROM_ALL traceroute.cpp)
|
||||
TARGET_LINK_LIBRARIES(traceroute ${CMAKE_THREAD_LIBS_INIT})
|
||||
ENDIF(HAVE_CXX11)
|
||||
|
||||
TARGET_LINK_LIBRARIES(traceroute ${CMAKE_THREAD_LIBS_INIT})
|
||||
TARGET_LINK_LIBRARIES(dns_stats ${CMAKE_THREAD_LIBS_INIT})
|
||||
ENDIF(TINS_HAVE_CXX11)
|
||||
IF(WIN32)
|
||||
MESSAGE(WARNING "Disabling portscan example since it doesn't compile on Windows.")
|
||||
ELSE()
|
||||
ADD_EXECUTABLE(portscan EXCLUDE_FROM_ALL portscan.cpp)
|
||||
TARGET_LINK_LIBRARIES(portscan ${CMAKE_THREAD_LIBS_INIT})
|
||||
ELSE(THREADS_FOUND)
|
||||
MESSAGE(WARNING "Disabling portscan and traceroute examples since pthreads library was not found.")
|
||||
ENDIF(THREADS_FOUND)
|
||||
ELSE(libtins_FOUND)
|
||||
MESSAGE(
|
||||
WARNING
|
||||
"Disabling examples since libtins is not installed. "
|
||||
"Run cmake again once it is installed in order to compile them."
|
||||
)
|
||||
ENDIF(libtins_FOUND)
|
||||
ENDIF()
|
||||
ELSE()
|
||||
MESSAGE(WARNING "Disabling portscan and traceroute examples since pthreads library was not found.")
|
||||
ENDIF()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -32,21 +32,25 @@
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::map;
|
||||
using std::bind;
|
||||
|
||||
using namespace Tins;
|
||||
|
||||
class arp_monitor {
|
||||
public:
|
||||
void run(Sniffer &sniffer);
|
||||
void run(Sniffer& sniffer);
|
||||
private:
|
||||
bool callback(const PDU &pdu);
|
||||
bool callback(const PDU& pdu);
|
||||
|
||||
std::map<IPv4Address, HWAddress<6>> addresses;
|
||||
map<IPv4Address, HWAddress<6>> addresses;
|
||||
};
|
||||
|
||||
void arp_monitor::run(Sniffer &sniffer)
|
||||
{
|
||||
void arp_monitor::run(Sniffer& sniffer) {
|
||||
sniffer.sniff_loop(
|
||||
std::bind(
|
||||
bind(
|
||||
&arp_monitor::callback,
|
||||
this,
|
||||
std::placeholders::_1
|
||||
@@ -54,36 +58,34 @@ void arp_monitor::run(Sniffer &sniffer)
|
||||
);
|
||||
}
|
||||
|
||||
bool arp_monitor::callback(const PDU &pdu)
|
||||
{
|
||||
bool arp_monitor::callback(const PDU& pdu) {
|
||||
// Retrieve the ARP layer
|
||||
const ARP &arp = pdu.rfind_pdu<ARP>();
|
||||
const ARP& arp = pdu.rfind_pdu<ARP>();
|
||||
// Is it an ARP reply?
|
||||
if(arp.opcode() == ARP::REPLY) {
|
||||
if (arp.opcode() == ARP::REPLY) {
|
||||
// Let's check if there's already an entry for this address
|
||||
auto iter = addresses.find(arp.sender_ip_addr());
|
||||
if(iter == addresses.end()) {
|
||||
if (iter == addresses.end()) {
|
||||
// We haven't seen this address. Save it.
|
||||
addresses.insert({ arp.sender_ip_addr(), arp.sender_hw_addr()});
|
||||
std::cout << "[INFO] " << arp.sender_ip_addr() << " is at "
|
||||
<< arp.sender_hw_addr() << std::endl;
|
||||
cout << "[INFO] " << arp.sender_ip_addr() << " is at "
|
||||
<< arp.sender_hw_addr() << std::endl;
|
||||
}
|
||||
else {
|
||||
// We've seen this address. If it's not the same HW address, inform it
|
||||
if(arp.sender_hw_addr() != iter->second) {
|
||||
std::cout << "[WARNING] " << arp.sender_ip_addr() << " is at "
|
||||
<< iter->second << " but also at " << arp.sender_hw_addr()
|
||||
<< std::endl;
|
||||
if (arp.sender_hw_addr() != iter->second) {
|
||||
cout << "[WARNING] " << arp.sender_ip_addr() << " is at "
|
||||
<< iter->second << " but also at " << arp.sender_hw_addr()
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int main(int argc, char* argv[]) {
|
||||
if(argc != 2) {
|
||||
std::cout << "Usage: " << *argv << " <interface>\n";
|
||||
cout << "Usage: " <<* argv << " <interface>" << endl;
|
||||
return 1;
|
||||
}
|
||||
arp_monitor monitor;
|
||||
@@ -92,9 +94,14 @@ int main(int argc, char *argv[])
|
||||
config.set_promisc_mode(true);
|
||||
config.set_filter("arp");
|
||||
|
||||
// Sniff on the provided interface in promiscuous mode
|
||||
Sniffer sniffer(argv[1], config);
|
||||
|
||||
// Only capture arp packets
|
||||
monitor.run(sniffer);
|
||||
try {
|
||||
// Sniff on the provided interface in promiscuous mode
|
||||
Sniffer sniffer(argv[1], config);
|
||||
|
||||
// Only capture arp packets
|
||||
monitor.run(sniffer);
|
||||
}
|
||||
catch (std::exception& ex) {
|
||||
std::cerr << "Error: " << ex.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -32,20 +32,29 @@
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <cstdlib>
|
||||
#include <unistd.h>
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif // _WIN32
|
||||
#include <tins/arp.h>
|
||||
#include <tins/network_interface.h>
|
||||
#include <tins/utils.h>
|
||||
#include <tins/ethernetII.h>
|
||||
#include <tins/packet_sender.h>
|
||||
|
||||
using namespace std;
|
||||
using std::cout;
|
||||
using std::runtime_error;
|
||||
using std::endl;
|
||||
|
||||
using namespace Tins;
|
||||
|
||||
|
||||
void do_arp_spoofing(NetworkInterface iface, IPv4Address gw, IPv4Address victim,
|
||||
const NetworkInterface::Info &info)
|
||||
{
|
||||
void do_arp_spoofing(NetworkInterface iface,
|
||||
IPv4Address gw,
|
||||
IPv4Address victim,
|
||||
const NetworkInterface::Info& info) {
|
||||
PacketSender sender;
|
||||
EthernetII::address_type gw_hw, victim_hw;
|
||||
|
||||
@@ -74,17 +83,23 @@ void do_arp_spoofing(NetworkInterface iface, IPv4Address gw, IPv4Address victim,
|
||||
* performed by any routers. */
|
||||
EthernetII to_gw = EthernetII(gw_hw, info.hw_addr) / gw_arp;
|
||||
EthernetII to_victim = EthernetII(victim_hw, info.hw_addr) / victim_arp;
|
||||
while(true) {
|
||||
while (true) {
|
||||
// Just send them once every 5 seconds.
|
||||
sender.send(to_gw, iface);
|
||||
sender.send(to_victim, iface);
|
||||
sleep(5);
|
||||
#ifdef _WIN32
|
||||
Sleep(5000);
|
||||
#else
|
||||
sleep(5);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if(argc != 3 && cout << "Usage: " << *argv << " <Gateway> <Victim>\n")
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 3) {
|
||||
cout << "Usage: " <<* argv << " <Gateway> <Victim>" << endl;
|
||||
return 1;
|
||||
}
|
||||
IPv4Address gw, victim;
|
||||
EthernetII::address_type own_hw;
|
||||
try {
|
||||
@@ -92,7 +107,7 @@ int main(int argc, char *argv[]) {
|
||||
gw = argv[1];
|
||||
victim = argv[2];
|
||||
}
|
||||
catch(...) {
|
||||
catch (...) {
|
||||
cout << "Invalid ip found...\n";
|
||||
return 2;
|
||||
}
|
||||
@@ -106,15 +121,15 @@ int main(int argc, char *argv[]) {
|
||||
// Find the interface hardware and ip address.
|
||||
info = iface.addresses();
|
||||
}
|
||||
catch(std::runtime_error &ex) {
|
||||
catch (runtime_error& ex) {
|
||||
cout << ex.what() << endl;
|
||||
return 3;
|
||||
}
|
||||
try {
|
||||
do_arp_spoofing(iface, gw, victim, info);
|
||||
}
|
||||
catch(std::runtime_error &ex) {
|
||||
std::cout << "Runtime error: " << ex.what() << std::endl;
|
||||
catch (runtime_error& ex) {
|
||||
cout << "Runtime error: " << ex.what() << endl;
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -32,21 +32,27 @@
|
||||
#include <string>
|
||||
#include <tins/tins.h>
|
||||
|
||||
using std::set;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::string;
|
||||
using std::runtime_error;
|
||||
|
||||
using namespace Tins;
|
||||
|
||||
class BeaconSniffer {
|
||||
public:
|
||||
void run(const std::string &iface);
|
||||
void run(const string& iface);
|
||||
private:
|
||||
typedef Dot11::address_type address_type;
|
||||
typedef std::set<address_type> ssids_type;
|
||||
typedef set<address_type> ssids_type;
|
||||
|
||||
bool callback(PDU &pdu);
|
||||
bool callback(PDU& pdu);
|
||||
|
||||
ssids_type ssids;
|
||||
};
|
||||
|
||||
void BeaconSniffer::run(const std::string &iface) {
|
||||
void BeaconSniffer::run(const std::string& iface) {
|
||||
SnifferConfiguration config;
|
||||
config.set_promisc_mode(true);
|
||||
config.set_filter("type mgt subtype beacon");
|
||||
@@ -55,28 +61,28 @@ void BeaconSniffer::run(const std::string &iface) {
|
||||
sniffer.sniff_loop(make_sniffer_handler(this, &BeaconSniffer::callback));
|
||||
}
|
||||
|
||||
bool BeaconSniffer::callback(PDU &pdu) {
|
||||
bool BeaconSniffer::callback(PDU& pdu) {
|
||||
// Get the Dot11 layer
|
||||
const Dot11Beacon &beacon = pdu.rfind_pdu<Dot11Beacon>();
|
||||
const Dot11Beacon& beacon = pdu.rfind_pdu<Dot11Beacon>();
|
||||
// All beacons must have from_ds == to_ds == 0
|
||||
if(!beacon.from_ds() && !beacon.to_ds()) {
|
||||
if (!beacon.from_ds() && !beacon.to_ds()) {
|
||||
// Get the AP address
|
||||
address_type addr = beacon.addr2();
|
||||
// Look it up in our set
|
||||
ssids_type::iterator it = ssids.find(addr);
|
||||
if(it == ssids.end()) {
|
||||
if (it == ssids.end()) {
|
||||
// First time we encounter this BSSID.
|
||||
try {
|
||||
/* If no ssid option is set, then Dot11::ssid will throw
|
||||
* a std::runtime_error.
|
||||
*/
|
||||
std::string ssid = beacon.ssid();
|
||||
string ssid = beacon.ssid();
|
||||
// Save it so we don't show it again.
|
||||
ssids.insert(addr);
|
||||
// Display the tuple "address - ssid".
|
||||
std::cout << addr << " - " << ssid << std::endl;
|
||||
cout << addr << " - " << ssid << endl;
|
||||
}
|
||||
catch(std::runtime_error&) {
|
||||
catch (runtime_error&) {
|
||||
// No ssid, just ignore it.
|
||||
}
|
||||
}
|
||||
@@ -85,10 +91,11 @@ bool BeaconSniffer::callback(PDU &pdu) {
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// By default, sniff wlan0
|
||||
std::string interface = "wlan0";
|
||||
if(argc == 2)
|
||||
interface = argv[1];
|
||||
if (argc != 2) {
|
||||
cout << "Usage: " <<* argv << " <interface>" << endl;
|
||||
return 1;
|
||||
}
|
||||
string interface = argv[1];
|
||||
BeaconSniffer sniffer;
|
||||
sniffer.run(interface);
|
||||
}
|
||||
|
||||
118
examples/defragmenter.cpp
Normal file
118
examples/defragmenter.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include "tins/ip.h"
|
||||
#include "tins/ip_reassembler.h"
|
||||
#include "tins/sniffer.h"
|
||||
#include "tins/packet_writer.h"
|
||||
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
using std::string;
|
||||
using std::exception;
|
||||
|
||||
using Tins::IPv4Reassembler;
|
||||
using Tins::IP;
|
||||
using Tins::Packet;
|
||||
using Tins::FileSniffer;
|
||||
using Tins::PacketWriter;
|
||||
using Tins::DataLinkType;
|
||||
|
||||
// This example reads packets from a pcap file and writes them to a new file.
|
||||
// If any IPv4 fragmented packets are found in the input file, then they will
|
||||
// be reassembled before writing them, so instead of the individual fragments
|
||||
// it will write the whole packet.
|
||||
|
||||
class Defragmenter {
|
||||
public:
|
||||
// Construct the sniffer and the packet writer using the sniffer's
|
||||
// data link type
|
||||
Defragmenter(const string& input_file, const string& output_file)
|
||||
: sniffer_(input_file),
|
||||
writer_(output_file, (PacketWriter::LinkType)sniffer_.link_type()),
|
||||
total_reassembled_(0) {
|
||||
|
||||
}
|
||||
|
||||
void run() {
|
||||
Packet packet;
|
||||
// Read packets and keep going until there's no more packets to read
|
||||
while (packet = sniffer_.next_packet()) {
|
||||
// Try to reassemble the packet
|
||||
IPv4Reassembler::PacketStatus status = reassembler_.process(*packet.pdu());
|
||||
|
||||
// If we did reassemble it, increase this counter
|
||||
if (status == IPv4Reassembler::REASSEMBLED) {
|
||||
total_reassembled_++;
|
||||
}
|
||||
|
||||
// Regardless, we'll write it into the output file unless it's fragmented
|
||||
// (and not yet reassembled)
|
||||
if (status != IPv4Reassembler::FRAGMENTED) {
|
||||
writer_.write(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t total_packets_reassembled() const {
|
||||
return total_reassembled_;
|
||||
}
|
||||
private:
|
||||
FileSniffer sniffer_;
|
||||
IPv4Reassembler reassembler_;
|
||||
PacketWriter writer_;
|
||||
uint64_t total_reassembled_;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 3) {
|
||||
cout << "Usage: " << argv[0] << " <input-file> <output-file>" << endl;
|
||||
return 1;
|
||||
}
|
||||
try {
|
||||
// Build the defragmented
|
||||
Defragmenter defragmenter(argv[1], argv[2]);
|
||||
cout << "Processing " << argv[1] << endl;
|
||||
cout << "Writing results to " << argv[2] << endl;
|
||||
|
||||
// Run!
|
||||
defragmenter.run();
|
||||
cout << "Done" << endl;
|
||||
cout << "Reassembled: " << defragmenter.total_packets_reassembled()
|
||||
<< " packet(s)" << endl;
|
||||
}
|
||||
catch (exception& ex) {
|
||||
cerr << "Error: " << ex.what() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -30,10 +30,12 @@
|
||||
#include <tins/tins.h>
|
||||
#include <iostream>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
using namespace Tins;
|
||||
|
||||
bool callback(const PDU &pdu)
|
||||
{
|
||||
bool callback(const PDU& pdu) {
|
||||
// The packet probably looks like this:
|
||||
//
|
||||
// EthernetII / IP / UDP / RawPDU
|
||||
@@ -43,18 +45,18 @@ bool callback(const PDU &pdu)
|
||||
DNS dns = pdu.rfind_pdu<RawPDU>().to<DNS>();
|
||||
|
||||
// Retrieve the queries and print the domain name:
|
||||
for(const auto &query : dns.queries())
|
||||
std::cout << query.dname() << std::endl;
|
||||
for (const auto& query : dns.queries()) {
|
||||
cout << query.dname() << std::endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int main(int argc, char* argv[]) {
|
||||
if(argc != 2) {
|
||||
std::cout << "Usage: " << *argv << " <interface>" << std::endl;
|
||||
cout << "Usage: " <<* argv << " <interface>" << endl;
|
||||
return 1;
|
||||
}
|
||||
// Sniff on the provided interface in promiscuos mode
|
||||
// Sniff on the provided interface in promiscuous mode
|
||||
SnifferConfiguration config;
|
||||
config.set_promisc_mode(true);
|
||||
// Only capture udp packets sent to port 53
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -30,12 +30,14 @@
|
||||
#include <tins/tins.h>
|
||||
#include <iostream>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
using namespace Tins;
|
||||
|
||||
PacketSender sender;
|
||||
|
||||
bool callback(const PDU &pdu)
|
||||
{
|
||||
bool callback(const PDU& pdu) {
|
||||
// The packet probably looks like this:
|
||||
//
|
||||
// EthernetII / IP / UDP / RawPDU
|
||||
@@ -48,13 +50,13 @@ bool callback(const PDU &pdu)
|
||||
DNS dns = udp.rfind_pdu<RawPDU>().to<DNS>();
|
||||
|
||||
// Is it a DNS query?
|
||||
if(dns.type() == DNS::QUERY) {
|
||||
if (dns.type() == DNS::QUERY) {
|
||||
// Let's see if there's any query for an "A" record.
|
||||
for(const auto &query : dns.queries()) {
|
||||
if(query.type() == DNS::A) {
|
||||
for (const auto& query : dns.queries()) {
|
||||
if (query.query_type() == DNS::A) {
|
||||
// Here's one! Let's add an answer.
|
||||
dns.add_answer(
|
||||
DNS::Resource(
|
||||
DNS::resource(
|
||||
query.dname(),
|
||||
"127.0.0.1",
|
||||
DNS::A,
|
||||
@@ -66,16 +68,16 @@ bool callback(const PDU &pdu)
|
||||
}
|
||||
}
|
||||
// Have we added some answers?
|
||||
if(dns.answers_count() > 0) {
|
||||
if (dns.answers_count() > 0) {
|
||||
// It's a response now
|
||||
dns.type(DNS::RESPONSE);
|
||||
// Recursion is available(just in case)
|
||||
dns.recursion_available(1);
|
||||
// Build our packet
|
||||
auto pkt = EthernetII(eth.src_addr(), eth.dst_addr()) /
|
||||
IP(ip.src_addr(), ip.dst_addr()) /
|
||||
UDP(udp.sport(), udp.dport()) /
|
||||
dns;
|
||||
IP(ip.src_addr(), ip.dst_addr()) /
|
||||
UDP(udp.sport(), udp.dport()) /
|
||||
dns;
|
||||
// Send it!
|
||||
sender.send(pkt);
|
||||
}
|
||||
@@ -83,15 +85,16 @@ bool callback(const PDU &pdu)
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int main(int argc, char* argv[]) {
|
||||
if(argc != 2) {
|
||||
std::cout << "Usage: " << *argv << " <interface>" << std::endl;
|
||||
cout << "Usage: " <<* argv << " <interface>" << endl;
|
||||
return 1;
|
||||
}
|
||||
// Sniff on the provided interface in promiscuos mode
|
||||
// Sniff on the provided interface in promiscuous mode
|
||||
SnifferConfiguration config;
|
||||
config.set_promisc_mode(true);
|
||||
// Use immediate mode so we get the packets as fast as we can
|
||||
config.set_immediate_mode(true);
|
||||
// Only capture udp packets sent to port 53
|
||||
config.set_filter("udp and dst port 53");
|
||||
Sniffer sniffer(argv[1], config);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -27,6 +27,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#define NOMINMAX
|
||||
#endif // _WIN32
|
||||
|
||||
// Fix for gcc 4.6
|
||||
#define _GLIBCXX_USE_NANOSLEEP
|
||||
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <chrono>
|
||||
@@ -35,6 +42,25 @@
|
||||
#include <algorithm>
|
||||
#include <tins/tins.h>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::thread;
|
||||
using std::string;
|
||||
using std::bind;
|
||||
using std::map;
|
||||
using std::mutex;
|
||||
using std::max;
|
||||
using std::min;
|
||||
using std::exception;
|
||||
using std::lock_guard;
|
||||
using std::tuple;
|
||||
using std::make_tuple;
|
||||
using std::this_thread::sleep_for;
|
||||
using std::chrono::seconds;
|
||||
using std::chrono::milliseconds;
|
||||
using std::chrono::duration_cast;
|
||||
using std::chrono::system_clock;
|
||||
|
||||
using namespace Tins;
|
||||
|
||||
// Holds the DNS response time statistics. The response time is
|
||||
@@ -42,8 +68,8 @@ using namespace Tins;
|
||||
template<typename Duration>
|
||||
class statistics {
|
||||
public:
|
||||
using duration_type = Duration;
|
||||
using locker_type = std::lock_guard<std::mutex>;
|
||||
typedef Duration duration_type;
|
||||
typedef lock_guard<mutex> locker_type;
|
||||
|
||||
struct information {
|
||||
duration_type average, worst;
|
||||
@@ -51,65 +77,63 @@ public:
|
||||
};
|
||||
|
||||
statistics()
|
||||
: m_duration(), m_worst(duration_type::min()), m_count()
|
||||
{
|
||||
: m_duration(), m_worst(duration_type::min()), m_count() {
|
||||
|
||||
}
|
||||
|
||||
void add_response_time(const duration_type& duration)
|
||||
{
|
||||
void add_response_time(const duration_type& duration) {
|
||||
locker_type _(m_lock);
|
||||
m_duration += duration;
|
||||
m_count++;
|
||||
m_worst = std::max(m_worst, duration);
|
||||
m_worst = max(m_worst, duration);
|
||||
}
|
||||
|
||||
information get_information() const
|
||||
{
|
||||
information get_information() const {
|
||||
locker_type _(m_lock);
|
||||
if(m_count == 0)
|
||||
if(m_count == 0) {
|
||||
return { };
|
||||
else
|
||||
}
|
||||
else {
|
||||
return { m_duration / m_count, m_worst, m_count };
|
||||
}
|
||||
};
|
||||
private:
|
||||
duration_type m_duration, m_worst;
|
||||
size_t m_count;
|
||||
mutable std::mutex m_lock;
|
||||
mutable mutex m_lock;
|
||||
};
|
||||
|
||||
// Sniffs and tracks DNS queries. When a matching DNS response is found,
|
||||
// the response time is added to a statistics object.
|
||||
//
|
||||
// This class performs *no cleanup* on data associated with queries that
|
||||
// This class performs* no cleanup* on data associated with queries that
|
||||
// weren't answered.
|
||||
class dns_monitor {
|
||||
public:
|
||||
// The response times are measured in milliseconds
|
||||
using duration_type = std::chrono::milliseconds;
|
||||
typedef milliseconds duration_type;
|
||||
// The statistics type used.
|
||||
using statistics_type = statistics<duration_type>;
|
||||
typedef statistics<duration_type> statistics_type;
|
||||
|
||||
void run(BaseSniffer& sniffer);
|
||||
const statistics_type& stats() const {
|
||||
return m_stats;
|
||||
}
|
||||
private:
|
||||
using packet_info = std::tuple<IPv4Address, IPv4Address, uint16_t>;
|
||||
using clock_type = std::chrono::steady_clock;
|
||||
using time_point_type = std::chrono::time_point<clock_type>;
|
||||
typedef tuple<IPv4Address, IPv4Address, uint16_t> packet_info;
|
||||
typedef system_clock clock_type;
|
||||
typedef clock_type::time_point time_point_type;
|
||||
|
||||
bool callback(const PDU& pdu);
|
||||
static packet_info make_packet_info(const PDU& pdu, const DNS& dns);
|
||||
|
||||
statistics_type m_stats;
|
||||
std::map<packet_info, time_point_type> m_packet_info;
|
||||
map<packet_info, time_point_type> m_packet_info;
|
||||
};
|
||||
|
||||
void dns_monitor::run(BaseSniffer& sniffer)
|
||||
{
|
||||
void dns_monitor::run(BaseSniffer& sniffer) {
|
||||
sniffer.sniff_loop(
|
||||
std::bind(
|
||||
bind(
|
||||
&dns_monitor::callback,
|
||||
this,
|
||||
std::placeholders::_1
|
||||
@@ -117,13 +141,12 @@ void dns_monitor::run(BaseSniffer& sniffer)
|
||||
);
|
||||
}
|
||||
|
||||
bool dns_monitor::callback(const PDU& pdu)
|
||||
{
|
||||
bool dns_monitor::callback(const PDU& pdu) {
|
||||
auto now = clock_type::now();
|
||||
auto dns = pdu.rfind_pdu<RawPDU>().to<DNS>();
|
||||
auto info = make_packet_info(pdu, dns);
|
||||
// If it's a query, add the sniff time to our map.
|
||||
if(dns.type() == DNS::QUERY) {
|
||||
if (dns.type() == DNS::QUERY) {
|
||||
m_packet_info.insert(
|
||||
std::make_pair(info, now)
|
||||
);
|
||||
@@ -131,11 +154,11 @@ bool dns_monitor::callback(const PDU& pdu)
|
||||
else {
|
||||
// It's a response, we need to find the query in our map.
|
||||
auto iter = m_packet_info.find(info);
|
||||
if(iter != m_packet_info.end()) {
|
||||
if (iter != m_packet_info.end()) {
|
||||
// We found the query, let's add the response time to the
|
||||
// statistics object.
|
||||
m_stats.add_response_time(
|
||||
std::chrono::duration_cast<duration_type>(now - iter->second)
|
||||
duration_cast<duration_type>(now - iter->second)
|
||||
);
|
||||
// Forget about the query.
|
||||
m_packet_info.erase(iter);
|
||||
@@ -148,44 +171,48 @@ bool dns_monitor::callback(const PDU& pdu)
|
||||
// hold the same DNS id as belonging to the same query.
|
||||
//
|
||||
// This function retrieves a tuple (addr, addr, id) that will achieve it.
|
||||
auto dns_monitor::make_packet_info(const PDU& pdu, const DNS& dns) -> packet_info
|
||||
{
|
||||
auto dns_monitor::make_packet_info(const PDU& pdu, const DNS& dns) -> packet_info {
|
||||
const auto& ip = pdu.rfind_pdu<IP>();
|
||||
return std::make_tuple(
|
||||
return make_tuple(
|
||||
// smallest address first
|
||||
std::min(ip.src_addr(), ip.dst_addr()),
|
||||
min(ip.src_addr(), ip.dst_addr()),
|
||||
// largest address second
|
||||
std::max(ip.src_addr(), ip.dst_addr()),
|
||||
max(ip.src_addr(), ip.dst_addr()),
|
||||
dns.id()
|
||||
);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if(argc != 2) {
|
||||
std::cout << "Usage: " << *argv << " <interface>\n";
|
||||
return 1;
|
||||
int main(int argc, char* argv[]) {
|
||||
string iface;
|
||||
if (argc == 2) {
|
||||
// Use the provided interface
|
||||
iface = argv[1];
|
||||
}
|
||||
else {
|
||||
// Use the default interface
|
||||
iface = NetworkInterface::default_interface().name();
|
||||
}
|
||||
try {
|
||||
SnifferConfiguration config;
|
||||
config.set_promisc_mode(true);
|
||||
config.set_filter("udp and dst port 53");
|
||||
Sniffer sniffer(argv[1], config);
|
||||
config.set_filter("udp and port 53");
|
||||
Sniffer sniffer(iface, config);
|
||||
dns_monitor monitor;
|
||||
std::thread thread(
|
||||
thread thread(
|
||||
[&]() {
|
||||
monitor.run(sniffer);
|
||||
}
|
||||
);
|
||||
while(true) {
|
||||
while (true) {
|
||||
auto info = monitor.stats().get_information();
|
||||
std::cout << "\rAverage " << info.average.count()
|
||||
<< "ms. Worst: " << info.worst.count() << "ms. Count: "
|
||||
<< info.count;
|
||||
std::cout.flush();
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
cout << "\rAverage " << info.average.count()
|
||||
<< "ms. Worst: " << info.worst.count() << "ms. Count: "
|
||||
<< info.count << " ";
|
||||
cout.flush();
|
||||
sleep_for(seconds(1));
|
||||
}
|
||||
}
|
||||
catch(std::exception& ex) {
|
||||
std::cout << "[-] Error: " << ex.what() << std::endl;
|
||||
catch (exception& ex) {
|
||||
cout << "[-] Error: " << ex.what() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
147
examples/http_requests.cpp
Normal file
147
examples/http_requests.cpp
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <boost/regex.hpp>
|
||||
#include "tins/tcp_ip/stream_follower.h"
|
||||
#include "tins/sniffer.h"
|
||||
|
||||
using std::string;
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
using std::exception;
|
||||
|
||||
using boost::regex;
|
||||
using boost::match_results;
|
||||
|
||||
using Tins::PDU;
|
||||
using Tins::Sniffer;
|
||||
using Tins::SnifferConfiguration;
|
||||
using Tins::TCPIP::Stream;
|
||||
using Tins::TCPIP::StreamFollower;
|
||||
|
||||
// This example captures and follows TCP streams seen on port 80. It will
|
||||
// wait until both the client and server send data and then apply a regex
|
||||
// to both payloads, extrating some information and printing it.
|
||||
|
||||
// Don't buffer more than 3kb of data in either request/response
|
||||
const size_t MAX_PAYLOAD = 3 * 1024;
|
||||
// The regex to be applied on the request. This will extract the HTTP
|
||||
// method being used, the request's path and the Host header value.
|
||||
regex request_regex("([\\w]+) ([^ ]+).+\r\nHost: ([\\d\\w\\.-]+)\r\n");
|
||||
// The regex to be applied on the response. This finds the response code.
|
||||
regex response_regex("HTTP/[^ ]+ ([\\d]+)");
|
||||
|
||||
void on_server_data(Stream& stream) {
|
||||
match_results<Stream::payload_type::const_iterator> client_match;
|
||||
match_results<Stream::payload_type::const_iterator> server_match;
|
||||
const Stream::payload_type& client_payload = stream.client_payload();
|
||||
const Stream::payload_type& server_payload = stream.server_payload();
|
||||
// Run the regexes on client/server payloads
|
||||
bool valid = regex_search(server_payload.begin(), server_payload.end(),
|
||||
server_match, response_regex) &&
|
||||
regex_search(client_payload.begin(), client_payload.end(),
|
||||
client_match, request_regex);
|
||||
// If we matched both the client and the server regexes
|
||||
if (valid) {
|
||||
// Extract all fields
|
||||
string method = string(client_match[1].first, client_match[1].second);
|
||||
string url = string(client_match[2].first, client_match[2].second);
|
||||
string host = string(client_match[3].first, client_match[3].second);
|
||||
string response_code = string(server_match[1].first, server_match[1].second);
|
||||
// Now print them
|
||||
cout << method << " http://" << host << url << " -> " << response_code << endl;
|
||||
|
||||
// Once we've seen the first request on this stream, ignore it
|
||||
stream.ignore_client_data();
|
||||
stream.ignore_server_data();
|
||||
}
|
||||
|
||||
// Just in case the server returns invalid data, stop at 3kb
|
||||
if (stream.server_payload().size() > MAX_PAYLOAD) {
|
||||
stream.ignore_server_data();
|
||||
}
|
||||
}
|
||||
|
||||
void on_client_data(Stream& stream) {
|
||||
// Don't hold more than 3kb of data from the client's flow
|
||||
if (stream.client_payload().size() > MAX_PAYLOAD) {
|
||||
stream.ignore_client_data();
|
||||
}
|
||||
}
|
||||
|
||||
void on_new_connection(Stream& stream) {
|
||||
stream.client_data_callback(&on_client_data);
|
||||
stream.server_data_callback(&on_server_data);
|
||||
// Don't automatically cleanup the stream's data, as we'll manage
|
||||
// the buffer ourselves and let it grow until we see a full request
|
||||
// and response
|
||||
stream.auto_cleanup_payloads(false);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 2) {
|
||||
cout << "Usage: " << argv[0] << " <interface>" << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
try {
|
||||
// Construct the sniffer configuration object
|
||||
SnifferConfiguration config;
|
||||
// Get packets as quickly as possible
|
||||
config.set_immediate_mode(true);
|
||||
// Only capture TCP traffic sent from/to port 80
|
||||
config.set_filter("tcp port 80");
|
||||
// Construct the sniffer we'll use
|
||||
Sniffer sniffer(argv[1], config);
|
||||
|
||||
cout << "Starting capture on interface " << argv[1] << endl;
|
||||
|
||||
// Now construct the stream follower
|
||||
StreamFollower follower;
|
||||
// We just need to specify the callback to be executed when a new
|
||||
// stream is captured. In this stream, you should define which callbacks
|
||||
// will be executed whenever new data is sent on that stream
|
||||
// (see on_new_connection)
|
||||
follower.new_stream_callback(&on_new_connection);
|
||||
// Now start capturing. Every time there's a new packet, call
|
||||
// follower.process_packet
|
||||
sniffer.sniff_loop([&](PDU& packet) {
|
||||
follower.process_packet(packet);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
catch (exception& ex) {
|
||||
cerr << "Error: " << ex.what() << endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
140
examples/icmp_responses.cpp
Normal file
140
examples/icmp_responses.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <tins/tins.h>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::bind;
|
||||
using std::string;
|
||||
using std::runtime_error;
|
||||
using std::exception;
|
||||
|
||||
using namespace Tins;
|
||||
|
||||
// This class captured packets on an interface, using the specified filter
|
||||
// and will respond with ICMP error packets whenever a packet is captured.
|
||||
// The response mechanism is pretty naive as it generates a packet which
|
||||
// has swapped HW and IP addresses (dst as src, src as dst).
|
||||
class ICMPResponder {
|
||||
public:
|
||||
// Use the given interface and ICMP type/code on responses
|
||||
ICMPResponder(string iface, int type, int code)
|
||||
: m_iface(iface), m_sender(iface), m_type(type), m_code(code) {
|
||||
|
||||
}
|
||||
|
||||
// Run using the given filter
|
||||
void run(const string& filter) {
|
||||
// Initialize the configuration
|
||||
SnifferConfiguration config;
|
||||
// Use promiscuous mode
|
||||
config.set_promisc_mode(true);
|
||||
// Use this packet filter
|
||||
config.set_filter(filter);
|
||||
// Use immediate mode (we don't want to buffer packets, we want the mright away).
|
||||
config.set_immediate_mode(true);
|
||||
|
||||
// Now create the Sniffer
|
||||
Sniffer sniffer(m_iface, config);
|
||||
if (sniffer.link_type() != DLT_EN10MB) {
|
||||
throw runtime_error("Ethernet interfaces only supported");
|
||||
}
|
||||
// Start the sniffing! For each packet, ICMPReponder::callback will be called
|
||||
sniffer.sniff_loop(bind(&ICMPResponder::callback, this, std::placeholders::_1));
|
||||
}
|
||||
private:
|
||||
// Extracts the payload to be used over the ICMP layer in the response.
|
||||
// This will be the entire IP header + 8 bytes of the next header.
|
||||
RawPDU extract_icmp_payload(IP& pdu) {
|
||||
PDU::serialization_type buffer = pdu.serialize();
|
||||
// Use whole IP + 8 bytes of next header.
|
||||
size_t end_index = pdu.header_size() + 8;
|
||||
return RawPDU(buffer.begin(), buffer.begin() + end_index);
|
||||
}
|
||||
|
||||
// Generates an ICMP response given a packet.
|
||||
EthernetII generate_response(PDU& pdu) {
|
||||
// Find Ethernet and IP headers.
|
||||
EthernetII& received_eth = pdu.rfind_pdu<EthernetII>();
|
||||
IP& received_ip = pdu.rfind_pdu<IP>();
|
||||
|
||||
// Create an Ethernet response, flipping the addresses
|
||||
EthernetII output(received_eth.src_addr(), received_eth.dst_addr());
|
||||
// Append an IP PDU, again flipping addresses.
|
||||
//output /= IP(received_ip.src_addr(), received_ip.dst_addr());
|
||||
output /= IP(received_ip.src_addr(), "8.8.8.8");
|
||||
|
||||
// Now generate the ICMP layer using the type and code provided.
|
||||
ICMP icmp;
|
||||
icmp.type(static_cast<ICMP::Flags>(m_type));
|
||||
icmp.code(m_code);
|
||||
// Append the ICMP layer to our packet
|
||||
output /= icmp;
|
||||
// Extract the payload to be used over ICMP.
|
||||
output /= extract_icmp_payload(received_ip);
|
||||
return output;
|
||||
}
|
||||
|
||||
// Packet capture callback
|
||||
bool callback(PDU& pdu) {
|
||||
// Generate a response for this packet
|
||||
EthernetII response = generate_response(pdu);
|
||||
// Send this packet!
|
||||
m_sender.send(response);
|
||||
return true;
|
||||
}
|
||||
|
||||
string m_iface;
|
||||
PacketSender m_sender;
|
||||
int m_type;
|
||||
int m_code;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
const int type = 3;
|
||||
const int code = 0;
|
||||
if (argc < 3) {
|
||||
cout << "Usage: " << argv[0] << " <interface> <pcap_filter>" << endl;
|
||||
return 1;
|
||||
}
|
||||
string iface = argv[1];
|
||||
string filter = argv[2];
|
||||
try {
|
||||
ICMPResponder responder(iface, type, code);
|
||||
responder.run(filter);
|
||||
}
|
||||
catch (exception& ex) {
|
||||
cout << "Error: " << ex.what() << endl;
|
||||
}
|
||||
}
|
||||
87
examples/interfaces_info.cpp
Normal file
87
examples/interfaces_info.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <tins/network_interface.h>
|
||||
|
||||
using std::cout;
|
||||
using std::wcout;
|
||||
using std::endl;
|
||||
using std::string;
|
||||
using std::ostringstream;
|
||||
|
||||
using namespace Tins;
|
||||
|
||||
int main() {
|
||||
// Get all interfaces and iterate over them.
|
||||
for (const NetworkInterface& iface : NetworkInterface::all()) {
|
||||
// Get the name of this interface
|
||||
string name = iface.name();
|
||||
|
||||
// "stringify" the status of the interface
|
||||
string status = iface.is_up() ? "up" : "down";
|
||||
|
||||
// Get this interface's information (addresses).
|
||||
NetworkInterface::Info info = iface.info();
|
||||
|
||||
// Now print all of this info.
|
||||
cout << name;
|
||||
|
||||
#ifdef _WIN32
|
||||
// If this is running on Windows, also print the friendly name
|
||||
wcout << " (" << iface.friendly_name() << ")";
|
||||
#endif // _WIN32
|
||||
cout << ": " << endl;
|
||||
|
||||
string ipv6_string;
|
||||
if (info.ipv6_addrs.empty()) {
|
||||
ipv6_string = "(none)";
|
||||
}
|
||||
else {
|
||||
ostringstream oss;
|
||||
for (size_t i = 0; i < info.ipv6_addrs.size(); ++i) {
|
||||
const NetworkInterface::IPv6Prefix& prefix = info.ipv6_addrs[i];
|
||||
if (i > 0) {
|
||||
oss << ", ";
|
||||
}
|
||||
oss << prefix.address << "/" << prefix.prefix_length;
|
||||
}
|
||||
ipv6_string = oss.str();
|
||||
}
|
||||
cout << " HW address: " << info.hw_addr << endl
|
||||
<< " IP address: " << info.ip_addr << endl
|
||||
<< " IPv6 addresses: " << ipv6_string << endl
|
||||
<< " Netmask: " << info.netmask << endl
|
||||
<< " Broadcast: " << info.bcast_addr << endl
|
||||
<< " Iface index: " << iface.id() << endl
|
||||
<< " Status: " << "interface " << status << endl << endl;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -44,22 +44,30 @@
|
||||
#include <tins/utils.h>
|
||||
#include <tins/packet_sender.h>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::vector;
|
||||
using std::pair;
|
||||
using std::setw;
|
||||
using std::string;
|
||||
using std::set;
|
||||
using std::runtime_error;
|
||||
|
||||
using namespace std;
|
||||
using namespace Tins;
|
||||
|
||||
typedef std::pair<Sniffer*, std::string> sniffer_data;
|
||||
typedef pair<Sniffer*, string> sniffer_data;
|
||||
|
||||
class Scanner {
|
||||
public:
|
||||
Scanner(const NetworkInterface& interface, const IPv4Address& address,
|
||||
const vector<string>& ports);
|
||||
Scanner(const NetworkInterface& interface,
|
||||
const IPv4Address& address,
|
||||
const vector<string>& ports);
|
||||
|
||||
void run();
|
||||
private:
|
||||
void send_syns(const NetworkInterface &iface, IPv4Address dest_ip);
|
||||
bool callback(PDU &pdu);
|
||||
static void *thread_proc(void *param);
|
||||
void send_syns(const NetworkInterface& iface, IPv4Address dest_ip);
|
||||
bool callback(PDU& pdu);
|
||||
static void* thread_proc(void* param);
|
||||
void launch_sniffer();
|
||||
|
||||
NetworkInterface iface;
|
||||
@@ -68,37 +76,35 @@ private:
|
||||
Sniffer sniffer;
|
||||
};
|
||||
|
||||
Scanner::Scanner(const NetworkInterface& interface, const IPv4Address& address,
|
||||
const vector<string>& ports)
|
||||
: iface(interface), host_to_scan(address), sniffer(interface.name())
|
||||
{
|
||||
Scanner::Scanner(const NetworkInterface& interface,
|
||||
const IPv4Address& address,
|
||||
const vector<string>& ports)
|
||||
: iface(interface), host_to_scan(address), sniffer(interface.name()) {
|
||||
sniffer.set_filter(
|
||||
"tcp and ip src " + address.to_string() + " and tcp[tcpflags] & (tcp-rst|tcp-syn) != 0"
|
||||
);
|
||||
for(size_t i = 0; i < ports.size(); ++i) {
|
||||
for (size_t i = 0; i < ports.size(); ++i) {
|
||||
ports_to_scan.insert(atoi(ports[i].c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
void *Scanner::thread_proc(void *param) {
|
||||
Scanner *data = (Scanner*)param;
|
||||
void* Scanner::thread_proc(void* param) {
|
||||
Scanner* data = (Scanner*)param;
|
||||
data->launch_sniffer();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Scanner::launch_sniffer()
|
||||
{
|
||||
void Scanner::launch_sniffer() {
|
||||
sniffer.sniff_loop(make_sniffer_handler(this, &Scanner::callback));
|
||||
}
|
||||
|
||||
/* Our scan handler. This will receive SYNs and RSTs and inform us
|
||||
* the scanned port's status.
|
||||
*/
|
||||
bool Scanner::callback(PDU &pdu)
|
||||
{
|
||||
bool Scanner::callback(PDU& pdu) {
|
||||
// Find the layers we want.
|
||||
const IP &ip = pdu.rfind_pdu<IP>();
|
||||
const TCP &tcp = pdu.rfind_pdu<TCP>();
|
||||
const IP& ip = pdu.rfind_pdu<IP>();
|
||||
const TCP& tcp = pdu.rfind_pdu<TCP>();
|
||||
// Check if the host that we're scanning sent this packet and
|
||||
// the source port is one of those that we scanned.
|
||||
if(ip.src_addr() == host_to_scan && ports_to_scan.count(tcp.sport()) == 1) {
|
||||
@@ -110,15 +116,14 @@ bool Scanner::callback(PDU &pdu)
|
||||
cout << "Port: " << setw(5) << tcp.sport() << " closed\n";
|
||||
}
|
||||
// Is SYN flag on? Then port is open!
|
||||
else if(tcp.flags() == (TCP::SYN | TCP::ACK)) {
|
||||
else if(tcp.has_flags(TCP::SYN | TCP::ACK)) {
|
||||
cout << "Port: " << setw(5) << tcp.sport() << " open\n";
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Scanner::run()
|
||||
{
|
||||
void Scanner::run() {
|
||||
pthread_t thread;
|
||||
// Launch our sniff thread.
|
||||
pthread_create(&thread, 0, &Scanner::thread_proc, this);
|
||||
@@ -126,25 +131,25 @@ void Scanner::run()
|
||||
send_syns(iface, host_to_scan);
|
||||
|
||||
// Wait for our sniffer.
|
||||
void *dummy;
|
||||
void* dummy;
|
||||
pthread_join(thread, &dummy);
|
||||
}
|
||||
|
||||
// Send syns to the given ip address, using the destination ports provided.
|
||||
void Scanner::send_syns(const NetworkInterface &iface, IPv4Address dest_ip) {
|
||||
void Scanner::send_syns(const NetworkInterface& iface, IPv4Address dest_ip) {
|
||||
// Retrieve the addresses.
|
||||
NetworkInterface::Info info = iface.addresses();
|
||||
PacketSender sender;
|
||||
// Allocate the IP PDU
|
||||
IP ip = IP(dest_ip, info.ip_addr) / TCP();
|
||||
// Get the reference to the TCP PDU
|
||||
TCP &tcp = ip.rfind_pdu<TCP>();
|
||||
TCP& tcp = ip.rfind_pdu<TCP>();
|
||||
// Set the SYN flag on.
|
||||
tcp.set_flag(TCP::SYN, 1);
|
||||
// Just some random port.
|
||||
tcp.sport(1337);
|
||||
cout << "Sending SYNs..." << endl;
|
||||
for(set<uint16_t>::const_iterator it = ports_to_scan.begin(); it != ports_to_scan.end(); ++it) {
|
||||
for (set<uint16_t>::const_iterator it = ports_to_scan.begin(); it != ports_to_scan.end(); ++it) {
|
||||
// Set the new port and send the packet!
|
||||
tcp.dport(*it);
|
||||
sender.send(ip);
|
||||
@@ -163,7 +168,7 @@ void Scanner::send_syns(const NetworkInterface &iface, IPv4Address dest_ip) {
|
||||
sender.send(eth, iface);
|
||||
}
|
||||
|
||||
void scan(int argc, char *argv[]) {
|
||||
void scan(int argc, char* argv[]) {
|
||||
IPv4Address ip(argv[1]);
|
||||
// Resolve the interface which will be our gateway
|
||||
NetworkInterface iface(ip);
|
||||
@@ -176,13 +181,15 @@ void scan(int argc, char *argv[]) {
|
||||
scanner.run();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if(argc < 3 && cout << "Usage: " << *argv << " <IPADDR> <port1> [port2] [port3]\n")
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc < 3) {
|
||||
cout << "Usage: " <<* argv << " <IPADDR> <port1> [port2] [port3]" << endl;
|
||||
return 1;
|
||||
}
|
||||
try {
|
||||
scan(argc, argv);
|
||||
}
|
||||
catch(std::runtime_error &ex) {
|
||||
catch(runtime_error& ex) {
|
||||
cout << "Error - " << ex.what() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
69
examples/route_table.cpp
Normal file
69
examples/route_table.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <tins/tins.h>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::setw;
|
||||
using std::vector;
|
||||
|
||||
using namespace Tins;
|
||||
|
||||
int main() {
|
||||
vector<Utils::RouteEntry> v4_entries = Utils::route_entries();
|
||||
cout << "IPv4 route table entries: " << endl
|
||||
<< "========================= " << endl;
|
||||
for (size_t i = 0; i < v4_entries.size(); ++i) {
|
||||
cout << "Entry " << setw(2) << i << ": " << endl
|
||||
<< "Interface: " << v4_entries[i].interface << endl
|
||||
<< "Destination: " << v4_entries[i].destination << endl
|
||||
<< "Gateway: " << v4_entries[i].gateway << endl
|
||||
<< "Genmask: " << v4_entries[i].mask << endl
|
||||
<< "Metric: " << v4_entries[i].metric << endl << endl;
|
||||
}
|
||||
|
||||
vector<Utils::Route6Entry> v6_entries = Utils::route6_entries();
|
||||
if (!v6_entries.empty()) {
|
||||
cout << endl
|
||||
<< "IPv6 route table entries: " << endl
|
||||
<< "========================= " << endl;
|
||||
for (size_t i = 0; i < v6_entries.size(); ++i) {
|
||||
cout << "Entry " << setw(2) << i << ": " << endl
|
||||
<< "Interface: " << v6_entries[i].interface << endl
|
||||
<< "Destination: " << v6_entries[i].destination << endl
|
||||
<< "Gateway: " << v6_entries[i].gateway << endl
|
||||
<< "Genmask: " << v6_entries[i].mask << endl
|
||||
<< "Metric: " << v6_entries[i].metric << endl << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
192
examples/stream_dump.cpp
Normal file
192
examples/stream_dump.cpp
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include "tins/tcp_ip/stream_follower.h"
|
||||
#include "tins/sniffer.h"
|
||||
#include "tins/packet.h"
|
||||
#include "tins/ip_address.h"
|
||||
#include "tins/ipv6_address.h"
|
||||
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
using std::bind;
|
||||
using std::string;
|
||||
using std::to_string;
|
||||
using std::ostringstream;
|
||||
using std::exception;
|
||||
|
||||
using Tins::Sniffer;
|
||||
using Tins::SnifferConfiguration;
|
||||
using Tins::PDU;
|
||||
using Tins::TCPIP::StreamFollower;
|
||||
using Tins::TCPIP::Stream;
|
||||
|
||||
// This example takes an interface and a port as an argument and
|
||||
// it listens for TCP streams on the given interface and port.
|
||||
// It will reassemble TCP streams and show the traffic sent by
|
||||
// both the client and the server.
|
||||
|
||||
// Convert the client endpoint to a readable string
|
||||
string client_endpoint(const Stream& stream) {
|
||||
ostringstream output;
|
||||
// Use the IPv4 or IPv6 address depending on which protocol the
|
||||
// connection uses
|
||||
if (stream.is_v6()) {
|
||||
output << stream.client_addr_v6();
|
||||
}
|
||||
else {
|
||||
output << stream.client_addr_v4();
|
||||
}
|
||||
output << ":" << stream.client_port();
|
||||
return output.str();
|
||||
}
|
||||
|
||||
// Convert the server endpoint to a readable string
|
||||
string server_endpoint(const Stream& stream) {
|
||||
ostringstream output;
|
||||
if (stream.is_v6()) {
|
||||
output << stream.server_addr_v6();
|
||||
}
|
||||
else {
|
||||
output << stream.server_addr_v4();
|
||||
}
|
||||
output << ":" << stream.server_port();
|
||||
return output.str();
|
||||
}
|
||||
|
||||
// Concat both endpoints to get a readable stream identifier
|
||||
string stream_identifier(const Stream& stream) {
|
||||
ostringstream output;
|
||||
output << client_endpoint(stream) << " - " << server_endpoint(stream);
|
||||
return output.str();
|
||||
}
|
||||
|
||||
// Whenever there's new client data on the stream, this callback is executed.
|
||||
void on_client_data(Stream& stream) {
|
||||
// Construct a string out of the contents of the client's payload
|
||||
string data(stream.client_payload().begin(), stream.client_payload().end());
|
||||
|
||||
// Now print it, prepending some information about the stream
|
||||
cout << client_endpoint(stream) << " >> "
|
||||
<< server_endpoint(stream) << ": " << endl << data << endl;
|
||||
}
|
||||
|
||||
// Whenever there's new server data on the stream, this callback is executed.
|
||||
// This does the same thing as on_client_data
|
||||
void on_server_data(Stream& stream) {
|
||||
string data(stream.server_payload().begin(), stream.server_payload().end());
|
||||
cout << server_endpoint(stream) << " >> "
|
||||
<< client_endpoint(stream) << ": " << endl << data << endl;
|
||||
}
|
||||
|
||||
// When a connection is closed, this callback is executed.
|
||||
void on_connection_closed(Stream& stream) {
|
||||
cout << "[+] Connection closed: " << stream_identifier(stream) << endl;
|
||||
}
|
||||
|
||||
// When a new connection is captured, this callback will be executed.
|
||||
void on_new_connection(Stream& stream) {
|
||||
if (stream.is_partial_stream()) {
|
||||
// We found a partial stream. This means this connection/stream had
|
||||
// been established before we started capturing traffic.
|
||||
//
|
||||
// In this case, we need to allow for the stream to catch up, as we
|
||||
// may have just captured an out of order packet and if we keep waiting
|
||||
// for the holes to be filled, we may end up waiting forever.
|
||||
//
|
||||
// Calling enable_recovery_mode will skip out of order packets that
|
||||
// fall withing the range of the given window size.
|
||||
// See Stream::enable_recover_mode for more information
|
||||
cout << "[+] New connection " << stream_identifier(stream) << endl;
|
||||
|
||||
// Enable recovery mode using a window of 10kb
|
||||
stream.enable_recovery_mode(10 * 1024);
|
||||
}
|
||||
else {
|
||||
// Print some information about the new connection
|
||||
cout << "[+] New connection " << stream_identifier(stream) << endl;
|
||||
}
|
||||
|
||||
// Now configure the callbacks on it.
|
||||
// First, we want on_client_data to be called every time there's new client data
|
||||
stream.client_data_callback(&on_client_data);
|
||||
|
||||
// Same thing for server data, but calling on_server_data
|
||||
stream.server_data_callback(&on_server_data);
|
||||
|
||||
// When the connection is closed, call on_connection_closed
|
||||
stream.stream_closed_callback(&on_connection_closed);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 3) {
|
||||
cout << "Usage: " << argv[0] << " <interface> <port>" << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
try {
|
||||
// Construct the sniffer configuration object
|
||||
SnifferConfiguration config;
|
||||
|
||||
// Only capture TCP traffic sent from/to the given port
|
||||
config.set_filter("tcp port " + to_string(stoi(string(argv[2]))));
|
||||
|
||||
// Construct the sniffer we'll use
|
||||
Sniffer sniffer(argv[1], config);
|
||||
|
||||
cout << "Starting capture on interface " << argv[1] << endl;
|
||||
|
||||
// Now construct the stream follower
|
||||
StreamFollower follower;
|
||||
|
||||
// We just need to specify the callback to be executed when a new
|
||||
// stream is captured. In this stream, you should define which callbacks
|
||||
// will be executed whenever new data is sent on that stream
|
||||
// (see on_new_connection)
|
||||
follower.new_stream_callback(&on_new_connection);
|
||||
|
||||
// Allow following partial TCP streams (e.g. streams that were
|
||||
// open before the sniffer started running)
|
||||
follower.follow_partial_streams(true);
|
||||
|
||||
// Now start capturing. Every time there's a new packet, call
|
||||
// follower.process_packet
|
||||
sniffer.sniff_loop([&](PDU& packet) {
|
||||
follower.process_packet(packet);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
catch (exception& ex) {
|
||||
cerr << "Error: " << ex.what() << endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
107
examples/tcp_connection_close.cpp
Normal file
107
examples/tcp_connection_close.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <tins/tins.h>
|
||||
|
||||
using std::string;
|
||||
using std::bind;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::exception;
|
||||
|
||||
using namespace Tins;
|
||||
|
||||
// This example will capture TCP packets and send packet that will reset
|
||||
// the connection when it captures a packet with the SYN and ACK flags on.
|
||||
class tcp_connection_closer {
|
||||
public:
|
||||
tcp_connection_closer() {
|
||||
|
||||
}
|
||||
|
||||
void run(const string& interface) {
|
||||
using std::placeholders::_1;
|
||||
// Make the PacketSender use this interface by default
|
||||
sender_.default_interface(interface);
|
||||
|
||||
// Create the sniffer configuration
|
||||
SnifferConfiguration config;
|
||||
config.set_filter("tcp");
|
||||
// We want to get the packets as fast as possible
|
||||
config.set_immediate_mode(true);
|
||||
// Create the sniffer and start the capture
|
||||
Sniffer sniffer(interface, config);
|
||||
sniffer.sniff_loop(bind(&tcp_connection_closer::callback, this, _1));
|
||||
}
|
||||
private:
|
||||
bool callback(const PDU& pdu) {
|
||||
const EthernetII& eth = pdu.rfind_pdu<EthernetII>();
|
||||
const IP& ip = pdu.rfind_pdu<IP>();
|
||||
const TCP& tcp = pdu.rfind_pdu<TCP>();
|
||||
// We'll only close a connection when seeing a SYN|ACK
|
||||
if (tcp.has_flags(TCP::SYN | TCP::ACK)) {
|
||||
// Create an ethernet header flipping the addresses
|
||||
EthernetII packet(eth.src_addr(), eth.dst_addr());
|
||||
// Do the same for IP
|
||||
packet /= IP(ip.src_addr(), ip.dst_addr());
|
||||
// Flip TCP ports
|
||||
TCP response_tcp(tcp.sport(), tcp.dport());
|
||||
// Set RST|ACK flags
|
||||
response_tcp.flags(TCP::RST | TCP::ACK);
|
||||
// Use the right sequence and ack numbers
|
||||
response_tcp.seq(tcp.ack_seq());
|
||||
response_tcp.ack_seq(tcp.seq());
|
||||
// Add this PDU to the packet we'll send
|
||||
packet /= response_tcp;
|
||||
// Send it!
|
||||
sender_.send(packet);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
PacketSender sender_;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 2) {
|
||||
cout << "Usage: " << *argv << " <interface>" << endl;
|
||||
return 1;
|
||||
}
|
||||
try {
|
||||
tcp_connection_closer closer;
|
||||
closer.run(argv[1]);
|
||||
}
|
||||
catch (exception& ex) {
|
||||
cout << "[-] Error: " << ex.what() << endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -27,15 +27,45 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#define NOMINMAX
|
||||
#endif // _WIN32
|
||||
|
||||
// Fix for gcc 4.6
|
||||
#define _GLIBCXX_USE_NANOSLEEP
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <cstdint>
|
||||
#include <random>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <limits>
|
||||
#include <mutex>
|
||||
#include <tins/tins.h>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::move;
|
||||
using std::map;
|
||||
using std::min;
|
||||
using std::setw;
|
||||
using std::atomic;
|
||||
using std::runtime_error;
|
||||
using std::string;
|
||||
using std::to_string;
|
||||
using std::thread;
|
||||
using std::this_thread::sleep_for;
|
||||
using std::lock_guard;
|
||||
using std::mutex;
|
||||
using std::random_device;
|
||||
using std::numeric_limits;
|
||||
using std::bind;
|
||||
using std::chrono::milliseconds;
|
||||
|
||||
using namespace Tins;
|
||||
|
||||
class Traceroute {
|
||||
@@ -43,20 +73,21 @@ public:
|
||||
typedef std::map<uint16_t, IPv4Address> result_type;
|
||||
|
||||
Traceroute(NetworkInterface interface, IPv4Address address)
|
||||
: iface(interface), addr(address) { }
|
||||
: iface(interface), addr(address), lowest_dest_ttl(numeric_limits<int>::max()) {
|
||||
sequence = random_device()() & 0xffff;
|
||||
}
|
||||
|
||||
result_type trace() {
|
||||
// ICMPs that aren't sent from us.
|
||||
SnifferConfiguration config;
|
||||
config.set_snap_len(500);
|
||||
config.set_promisc_mode(false);
|
||||
// ICMPs that aren't sent from us.
|
||||
config.set_filter(
|
||||
"ip proto \\icmp and not src host " + iface.addresses().ip_addr.to_string());
|
||||
Sniffer sniffer(iface.name(), config);
|
||||
|
||||
PacketSender sender;
|
||||
// Create our handler
|
||||
auto handler = std::bind(
|
||||
auto handler = bind(
|
||||
&Traceroute::sniff_callback,
|
||||
this,
|
||||
std::placeholders::_1
|
||||
@@ -64,90 +95,117 @@ public:
|
||||
// We're running
|
||||
running = true;
|
||||
// Start the sniff thread
|
||||
std::thread sniff_thread(
|
||||
&Sniffer::sniff_loop<decltype(handler)>,
|
||||
&sniffer,
|
||||
handler,
|
||||
0
|
||||
thread sniff_thread(
|
||||
[&]() {
|
||||
sniffer.sniff_loop(handler);
|
||||
}
|
||||
);
|
||||
send_packets(sender);
|
||||
sniff_thread.join();
|
||||
// If the final hop responded, add its address at the appropriate ttl
|
||||
if (lowest_dest_ttl != numeric_limits<int>::max()) {
|
||||
results[lowest_dest_ttl] = addr;
|
||||
}
|
||||
// Clear our results and return what we've found
|
||||
return std::move(results);
|
||||
return move(results);
|
||||
}
|
||||
private:
|
||||
typedef std::map<uint16_t, size_t> ttl_map;
|
||||
typedef map<uint16_t, size_t> ttl_map;
|
||||
|
||||
void send_packets(PacketSender &sender) {
|
||||
void send_packets(PacketSender& sender) {
|
||||
// ICMPs are icmp-requests by default
|
||||
IP ip = IP(addr, iface.addresses().ip_addr) / ICMP();
|
||||
// We'll find at most 10 hops.
|
||||
ICMP& icmp = ip.rfind_pdu<ICMP>();
|
||||
icmp.sequence(sequence);
|
||||
// We'll find at most 20 hops.
|
||||
|
||||
for(auto i = 1; i <= 10; ++i) {
|
||||
// Set this "unique" id
|
||||
ip.id(i);
|
||||
for (auto i = 1; i <= 20; ++i) {
|
||||
// Set this ICMP id
|
||||
icmp.id(i);
|
||||
// Set the time-to-live option
|
||||
ip.ttl(i);
|
||||
|
||||
// Critical section
|
||||
{
|
||||
std::lock_guard<std::mutex> _(lock);
|
||||
lock_guard<mutex> _(lock);
|
||||
ttls[i] = i;
|
||||
}
|
||||
|
||||
sender.send(ip);
|
||||
// Give him a little time
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
// Give it a little time
|
||||
sleep_for(milliseconds(100));
|
||||
}
|
||||
running = false;
|
||||
sender.send(ip);
|
||||
}
|
||||
|
||||
bool sniff_callback(PDU &pdu) {
|
||||
const IP &ip = pdu.rfind_pdu<IP>();
|
||||
ttl_map::const_iterator iter;
|
||||
// Fetch the IP PDU attached to the ICMP response
|
||||
const IP inner_ip = pdu.rfind_pdu<RawPDU>().to<IP>();
|
||||
// Critical section
|
||||
{
|
||||
std::lock_guard<std::mutex> _(lock);
|
||||
iter = ttls.find(inner_ip.id());
|
||||
}
|
||||
bool sniff_callback(PDU& pdu) {
|
||||
// Find IP and ICMP PDUs
|
||||
const IP& ip = pdu.rfind_pdu<IP>();
|
||||
const ICMP& icmp = pdu.rfind_pdu<ICMP>();
|
||||
// Check if this is an ICMP TTL exceeded error response
|
||||
if (icmp.type() == ICMP::TIME_EXCEEDED) {
|
||||
// Fetch the IP PDU attached to the ICMP response
|
||||
const IP inner_ip = pdu.rfind_pdu<RawPDU>().to<IP>();
|
||||
// Now get the ICMP layer
|
||||
const ICMP& inner_icmp = inner_ip.rfind_pdu<ICMP>();
|
||||
// Make sure this is one of our packets.
|
||||
if (inner_icmp.sequence() == sequence) {
|
||||
ttl_map::const_iterator iter;
|
||||
|
||||
// It's an actual response
|
||||
if(iter != ttls.end()) {
|
||||
// Store it
|
||||
results[inner_ip.id()] = ip.src_addr();
|
||||
// Critical section
|
||||
{
|
||||
std::lock_guard<std::mutex> _(lock);
|
||||
iter = ttls.find(inner_icmp.id());
|
||||
}
|
||||
|
||||
// It's an actual response
|
||||
if(iter != ttls.end()) {
|
||||
// Store it
|
||||
results[inner_icmp.id()] = ip.src_addr();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Otherwise, this could be the final hop making an echo response
|
||||
else if (icmp.type() == ICMP::ECHO_REPLY && icmp.sequence() == sequence &&
|
||||
ip.src_addr() == addr) {
|
||||
// Keep the lowest ttl seen for the destination.
|
||||
lowest_dest_ttl = min(lowest_dest_ttl, static_cast<int>(icmp.id()));
|
||||
}
|
||||
return running;
|
||||
}
|
||||
|
||||
NetworkInterface iface;
|
||||
IPv4Address addr;
|
||||
std::atomic<bool> running;
|
||||
atomic<bool> running;
|
||||
ttl_map ttls;
|
||||
result_type results;
|
||||
std::mutex lock;
|
||||
mutex lock;
|
||||
uint16_t sequence;
|
||||
int lowest_dest_ttl;
|
||||
};
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if(argc <= 1 && std::cout << "Usage: " << *argv << " <IP_ADDRESS>\n")
|
||||
if (argc <= 1) {
|
||||
cout << "Usage: " <<* argv << " <ip_address>" << endl;
|
||||
return 1;
|
||||
}
|
||||
try {
|
||||
IPv4Address addr((std::string(argv[1])));
|
||||
IPv4Address addr = string(argv[1]);
|
||||
Traceroute tracer(addr, addr);
|
||||
auto results = tracer.trace();
|
||||
if(results.empty())
|
||||
std::cout << "No hops found" << std::endl;
|
||||
if (results.empty()) {
|
||||
cout << "No hops found" << endl;
|
||||
}
|
||||
else {
|
||||
std::cout << "Results: " << std::endl;
|
||||
for(const auto &entry : results) {
|
||||
std::cout << entry.first << " - " << entry.second << std::endl;
|
||||
cout << "Results: " << endl;
|
||||
for(const auto& entry : results) {
|
||||
cout << setw(2) << entry.first << " - " << entry.second << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(std::runtime_error &ex) {
|
||||
std::cout << "Error - " << ex.what() << std::endl;
|
||||
catch (runtime_error& ex) {
|
||||
cout << "Error - " << ex.what() << endl;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -41,11 +41,11 @@ std::set<HWAddress<6>> addrs;
|
||||
const HWAddress<3> expected_oui("00:50:F2");
|
||||
|
||||
bool handler(const PDU& pdu) {
|
||||
const Dot11Beacon &beacon = pdu.rfind_pdu<Dot11Beacon>();
|
||||
const Dot11Beacon& beacon = pdu.rfind_pdu<Dot11Beacon>();
|
||||
// Only process it once
|
||||
if(addrs.insert(beacon.addr3()).second) {
|
||||
// Iterate the tagged options
|
||||
for(const auto &opt : beacon.options()) {
|
||||
for(const auto& opt : beacon.options()) {
|
||||
// Is this a vendor-specific tag?
|
||||
if(opt.option() == Dot11::VENDOR_SPECIFIC) {
|
||||
// Make sure there's enough size for the OUI + identifier
|
||||
@@ -63,9 +63,9 @@ bool handler(const PDU& pdu) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int main(int argc, char* argv[]) {
|
||||
if(argc != 2) {
|
||||
std::cout << "Usage: " << *argv << " <DEVICE>\n";
|
||||
std::cout << "Usage: " <<* argv << " <DEVICE>\n";
|
||||
return 1;
|
||||
}
|
||||
// Only sniff beacons
|
||||
|
||||
1
googletest
Submodule
1
googletest
Submodule
Submodule googletest added at 13206d6f53
@@ -1 +0,0 @@
|
||||
ADD_SUBDIRECTORY(tins)
|
||||
@@ -1,7 +0,0 @@
|
||||
FILE(GLOB INCLUDE_FILES "*.h")
|
||||
INSTALL(
|
||||
FILES ${INCLUDE_FILES}
|
||||
DESTINATION include/tins
|
||||
COMPONENT Headers
|
||||
)
|
||||
ADD_SUBDIRECTORY(dot11)
|
||||
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
@@ -30,10 +30,10 @@
|
||||
#ifndef TINS_ADDRESS_RANGE
|
||||
#define TINS_ADDRESS_RANGE
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iterator>
|
||||
#include "endianness.h"
|
||||
#include "internals.h"
|
||||
#include <tins/endianness.h>
|
||||
#include <tins/exceptions.h>
|
||||
#include <tins/detail/address_helpers.h>
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
@@ -53,9 +53,8 @@ public:
|
||||
*
|
||||
* \param first The address held by this iterator.
|
||||
*/
|
||||
AddressRangeIterator(const value_type &addr)
|
||||
: addr(addr), reached_end(false)
|
||||
{
|
||||
AddressRangeIterator(const value_type& address)
|
||||
: address_(address), reached_end_(false) {
|
||||
|
||||
}
|
||||
|
||||
@@ -64,24 +63,23 @@ public:
|
||||
*
|
||||
* \param first The address held by this iterator.
|
||||
*/
|
||||
AddressRangeIterator(const value_type &address, end_iterator)
|
||||
: addr(address)
|
||||
{
|
||||
reached_end = Internals::increment(addr);
|
||||
AddressRangeIterator(const value_type& address, end_iterator)
|
||||
: address_(address) {
|
||||
reached_end_ = Internals::increment(address_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current address pointed by this iterator.
|
||||
*/
|
||||
const value_type& operator*() const {
|
||||
return addr;
|
||||
return address_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a pointer to the current address pointed by this iterator.
|
||||
*/
|
||||
const value_type* operator->() const {
|
||||
return &addr;
|
||||
return& address_;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,8 +87,8 @@ public:
|
||||
*
|
||||
* \param rhs The iterator with which to compare.
|
||||
*/
|
||||
bool operator==(const AddressRangeIterator &rhs) const {
|
||||
return reached_end == rhs.reached_end && addr == rhs.addr;
|
||||
bool operator==(const AddressRangeIterator& rhs) const {
|
||||
return reached_end_ == rhs.reached_end_ && address_ == rhs.address_;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,7 +96,7 @@ public:
|
||||
*
|
||||
* \param rhs The iterator with which to compare.
|
||||
*/
|
||||
bool operator!=(const AddressRangeIterator &rhs) const {
|
||||
bool operator!=(const AddressRangeIterator& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
@@ -106,8 +104,8 @@ public:
|
||||
* Increments this iterator.
|
||||
*/
|
||||
AddressRangeIterator& operator++() {
|
||||
reached_end = Internals::increment(addr);
|
||||
return *this;
|
||||
reached_end_ = Internals::increment(address_);
|
||||
return* this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,47 +117,47 @@ public:
|
||||
return copy;
|
||||
}
|
||||
private:
|
||||
Address addr;
|
||||
bool reached_end;
|
||||
Address address_;
|
||||
bool reached_end_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Represents a range of addresses.
|
||||
*
|
||||
* This class provides a begin()/end() interface which allows
|
||||
* iterating through every address stored in it.
|
||||
* iterating through every address stored in it.
|
||||
*
|
||||
* Note that when iterating a range that was created using
|
||||
* operator/(IPv4Address, int) and the analog for IPv6, the
|
||||
* operator/(IPv4Address, int) and the analog for IPv6, the
|
||||
* network and broadcast addresses are discarded:
|
||||
*
|
||||
* \code
|
||||
* auto range = IPv4Address("192.168.5.0") / 24;
|
||||
* for(const auto &addr : range) {
|
||||
* for(const auto& addr : range) {
|
||||
* // process 192.168.5.1-254, .0 and .255 are discarded
|
||||
* process(addr);
|
||||
* }
|
||||
*
|
||||
* // That's only valid for iteration, not for AddressRange<>::contains
|
||||
*
|
||||
*
|
||||
* assert(range.contains("192.168.5.0")); // works
|
||||
* assert(range.contains("192.168.5.255")); // works
|
||||
* \endcode
|
||||
*
|
||||
* Ranges created using AddressRange(address_type, address_type)
|
||||
* Ranges created using AddressRange(address_type, address_type)
|
||||
* will allow the iteration over the entire range:
|
||||
*
|
||||
* \code
|
||||
* AddressRange<IPv4Address> range("192.168.5.0", "192.168.5.255");
|
||||
* for(const auto &addr : range) {
|
||||
* for(const auto& addr : range) {
|
||||
* // process 192.168.5.0-255, no addresses are discarded
|
||||
* process(addr);
|
||||
* }
|
||||
*
|
||||
*
|
||||
* assert(range.contains("192.168.5.0")); // still valid
|
||||
* assert(range.contains("192.168.5.255")); // still valid
|
||||
* \endcode
|
||||
*
|
||||
*
|
||||
*/
|
||||
template<typename Address>
|
||||
class AddressRange {
|
||||
@@ -188,20 +186,20 @@ public:
|
||||
* The range will consist of the addresses [first, last].
|
||||
*
|
||||
* If only_hosts is true, then the network and broadcast addresses
|
||||
* will not be available when iterating the range.
|
||||
* will not be available when iterating the range.
|
||||
*
|
||||
* If last < first, an std::runtime_error exception is thrown.
|
||||
*
|
||||
*
|
||||
* \param first The first address in the range.
|
||||
* \param last The last address(inclusive) in the range.
|
||||
* \param only_hosts Indicates whether only host addresses
|
||||
* should be accessed when using iterators.
|
||||
*/
|
||||
AddressRange(const address_type &first, const address_type &last, bool only_hosts = false)
|
||||
: first(first), last(last), only_hosts(only_hosts)
|
||||
{
|
||||
if(last < first)
|
||||
throw std::runtime_error("Invalid address range");
|
||||
AddressRange(const address_type& first, const address_type& last, bool only_hosts = false)
|
||||
: first_(first), last_(last), only_hosts_(only_hosts){
|
||||
if (last_ < first_) {
|
||||
throw exception_base("Invalid address range");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -211,10 +209,10 @@ public:
|
||||
* \param first The base address.
|
||||
* \param mask The network mask to be used.
|
||||
*/
|
||||
static AddressRange from_mask(const address_type &first, const address_type &mask) {
|
||||
static AddressRange from_mask(const address_type& first, const address_type& mask) {
|
||||
return AddressRange<address_type>(
|
||||
first,
|
||||
Internals::last_address_from_mask(first, mask),
|
||||
first & mask,
|
||||
Internals::last_address_from_mask(first, mask),
|
||||
true
|
||||
);
|
||||
}
|
||||
@@ -224,8 +222,8 @@ public:
|
||||
* \param addr The address to test.
|
||||
* \return a bool indicating whether the address is in the range.
|
||||
*/
|
||||
bool contains(const address_type &addr) const {
|
||||
return (first < addr && addr < last) || addr == first || addr == last;
|
||||
bool contains(const address_type& addr) const {
|
||||
return (first_ < addr && addr < last_) || addr == first_ || addr == last_;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -233,9 +231,10 @@ public:
|
||||
* \brief const_iterator pointing to the beginning of this range.
|
||||
*/
|
||||
const_iterator begin() const {
|
||||
address_type addr = first;
|
||||
if(only_hosts)
|
||||
address_type addr = first_;
|
||||
if (only_hosts_) {
|
||||
Internals::increment(addr);
|
||||
}
|
||||
return const_iterator(addr);
|
||||
}
|
||||
|
||||
@@ -244,43 +243,46 @@ public:
|
||||
* \brief const_iterator pointing to the end of this range.
|
||||
*/
|
||||
const_iterator end() const {
|
||||
address_type addr = last;
|
||||
if(only_hosts)
|
||||
address_type addr = last_;
|
||||
if (only_hosts_) {
|
||||
Internals::decrement(addr);
|
||||
}
|
||||
return const_iterator(addr, typename const_iterator::end_iterator());
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Indicates whether this range is iterable.
|
||||
*
|
||||
* Iterable ranges are those for which there is at least one
|
||||
* Iterable ranges are those for which there is at least one
|
||||
* address that could represent a host. For IPv4 ranges, a /31 or
|
||||
* /32 ranges does not contain any, therefore it's not iterable.
|
||||
* The same is true for /127 and /128 IPv6 ranges.
|
||||
*
|
||||
* If is_iterable returns false for a range, then iterating it
|
||||
* through the iterators returned by begin() and end() is
|
||||
* undefined.
|
||||
*
|
||||
* through the iterators returned by begin() and end() is
|
||||
* undefined.
|
||||
*
|
||||
* \return bool indicating whether this range is iterable.
|
||||
*/
|
||||
bool is_iterable() const {
|
||||
// Since first < last, it's iterable
|
||||
if(!only_hosts)
|
||||
if (!only_hosts_) {
|
||||
return true;
|
||||
}
|
||||
// We need that distance(first, last) >= 4
|
||||
address_type addr(first);
|
||||
for(int i = 0; i < 3; ++i) {
|
||||
address_type addr(first_);
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
// If there's overflow before the last iteration, we're done
|
||||
if(Internals::increment(addr) && i != 2)
|
||||
if (Internals::increment(addr) && i != 2) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// If addr <= last, it's OK.
|
||||
return addr < last || addr == last;
|
||||
return addr < last_ || addr == last_;
|
||||
}
|
||||
private:
|
||||
address_type first, last;
|
||||
bool only_hosts;
|
||||
address_type first_, last_;
|
||||
bool only_hosts_;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -299,12 +301,13 @@ typedef AddressRange<IPv6Address> IPv6Range;
|
||||
* \param mask The bit-length of the prefix.
|
||||
*/
|
||||
template<size_t n>
|
||||
AddressRange<HWAddress<n> > operator/(const HWAddress<n> &addr, int mask) {
|
||||
if(mask > 48)
|
||||
AddressRange<HWAddress<n> > operator/(const HWAddress<n>& addr, int mask) {
|
||||
if (mask > 48) {
|
||||
throw std::logic_error("Prefix length cannot exceed 48");
|
||||
}
|
||||
HWAddress<n> last_addr;
|
||||
typename HWAddress<n>::iterator it = last_addr.begin();
|
||||
while(mask > 8) {
|
||||
while (mask > 8) {
|
||||
*it = 0xff;
|
||||
++it;
|
||||
mask -= 8;
|
||||
@@ -318,14 +321,14 @@ AddressRange<HWAddress<n> > operator/(const HWAddress<n> &addr, int mask) {
|
||||
* \param addr The range's first address.
|
||||
* \param mask The bit-length of the prefix.
|
||||
*/
|
||||
IPv6Range operator/(const IPv6Address &addr, int mask);
|
||||
IPv6Range operator/(const IPv6Address& addr, int mask);
|
||||
|
||||
/**
|
||||
* \brief Constructs an IPv4Range from a base IPv4Address and a mask.
|
||||
* \param addr The range's first address.
|
||||
* \param mask The bit-length of the prefix.
|
||||
*/
|
||||
IPv4Range operator/(const IPv4Address &addr, int mask);
|
||||
IPv4Range operator/(const IPv4Address& addr, int mask);
|
||||
} // namespace Tins
|
||||
|
||||
#endif // TINS_ADDRESS_RANGE
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -31,287 +31,314 @@
|
||||
#ifndef TINS_ARP_H
|
||||
#define TINS_ARP_H
|
||||
|
||||
#include "macros.h"
|
||||
#include "pdu.h"
|
||||
#include "endianness.h"
|
||||
#include "hw_address.h"
|
||||
#include "ip_address.h"
|
||||
#include <tins/macros.h>
|
||||
#include <tins/pdu.h>
|
||||
#include <tins/endianness.h>
|
||||
#include <tins/hw_address.h>
|
||||
#include <tins/ip_address.h>
|
||||
|
||||
namespace Tins {
|
||||
class NetworkInterface;
|
||||
class EthernetII;
|
||||
|
||||
class NetworkInterface;
|
||||
class EthernetII;
|
||||
|
||||
/**
|
||||
* \class ARP
|
||||
* \brief Represents an ARP PDU.
|
||||
*
|
||||
*/
|
||||
class TINS_API ARP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* The type of the hardware address.
|
||||
*/
|
||||
typedef HWAddress<6> hwaddress_type;
|
||||
|
||||
/**
|
||||
* The type of the IP address.
|
||||
*/
|
||||
typedef IPv4Address ipaddress_type;
|
||||
|
||||
/**
|
||||
* \class ARP
|
||||
* \brief Represents an ARP PDU.
|
||||
*
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
class ARP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* The type of the hardware address.
|
||||
*/
|
||||
typedef HWAddress<6> hwaddress_type;
|
||||
|
||||
/**
|
||||
* The type of the IP address.
|
||||
*/
|
||||
typedef IPv4Address ipaddress_type;
|
||||
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::ARP;
|
||||
|
||||
/**
|
||||
* \brief Enum which indicates the type of ARP packet.
|
||||
*/
|
||||
enum Flags {
|
||||
REQUEST = 0x0001,
|
||||
REPLY = 0x0002
|
||||
};
|
||||
static const PDU::PDUType pdu_flag = PDU::ARP;
|
||||
|
||||
/**
|
||||
* \brief Constructs an ARP object using the provided addresses.
|
||||
*
|
||||
* ARP requests and replies can be constructed easily using
|
||||
* ARP::make_arp_request/reply static member functions.
|
||||
*
|
||||
* \sa ARP::make_arp_request
|
||||
* \sa ARP::make_arp_reply
|
||||
*
|
||||
* \param target_ip The target IP address.
|
||||
* \param sender_ip The sender IP address.
|
||||
* \param target_hw The target hardware address.
|
||||
* \param sender_hw The sender hardware address.
|
||||
*/
|
||||
ARP(ipaddress_type target_ip = ipaddress_type(),
|
||||
ipaddress_type sender_ip = ipaddress_type(),
|
||||
const hwaddress_type &target_hw = hwaddress_type(),
|
||||
const hwaddress_type &sender_hw = hwaddress_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs an ARP object from a buffer.
|
||||
*
|
||||
* If there is not enough size for an ARP header in the buffer,
|
||||
* a malformed_packet exception is thrown.
|
||||
*
|
||||
* If the buffer is bigger than the size of the ARP header,
|
||||
* then the extra data is stored in a RawPDU.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
ARP(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/* Getters */
|
||||
/**
|
||||
* \brief Getter for the sender's hardware address.
|
||||
*
|
||||
* \return The sender hardware address.
|
||||
*/
|
||||
hwaddress_type sender_hw_addr() const { return _arp.ar_sha; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the sender's IP address.
|
||||
*
|
||||
* \return The sender IP address.
|
||||
*/
|
||||
ipaddress_type sender_ip_addr() const { return ipaddress_type(_arp.ar_sip); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the target's hardware address.
|
||||
*
|
||||
* \return The target hardware address.
|
||||
*/
|
||||
hwaddress_type target_hw_addr() const { return _arp.ar_tha; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the target's IP address.
|
||||
*
|
||||
* \return The target IP address.
|
||||
*/
|
||||
ipaddress_type target_ip_addr() const { return ipaddress_type(_arp.ar_tip); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the hardware address format field.
|
||||
*
|
||||
* \return The hardware address format.
|
||||
*/
|
||||
uint16_t hw_addr_format() const { return Endian::be_to_host(_arp.ar_hrd); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the protocol address format field.
|
||||
*
|
||||
* \return The protocol address format.
|
||||
*/
|
||||
uint16_t prot_addr_format() const { return Endian::be_to_host(_arp.ar_pro); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the hardware address length field.
|
||||
*
|
||||
* \return The hardware address length.
|
||||
*/
|
||||
uint8_t hw_addr_length() const { return _arp.ar_hln; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the protocol address length field.
|
||||
*
|
||||
* \return The protocol address length.
|
||||
*/
|
||||
uint8_t prot_addr_length() const { return _arp.ar_pln; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the ARP opcode field.
|
||||
*
|
||||
* \return The ARP opcode.
|
||||
*/
|
||||
uint16_t opcode() const { return Endian::be_to_host(_arp.ar_op); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the header size.
|
||||
* \return Returns the ARP header size.
|
||||
* \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the sender's hardware address.
|
||||
*
|
||||
* \param new_snd_hw_addr The new sender hardware address.
|
||||
*/
|
||||
void sender_hw_addr(const hwaddress_type &new_snd_hw_addr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the sender's IP address.
|
||||
*
|
||||
* \param new_snd_ip_addr The new sender IP address.
|
||||
*/
|
||||
void sender_ip_addr(ipaddress_type new_snd_ip_addr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the target's hardware address.
|
||||
*
|
||||
* \param new_tgt_hw_addr The new target hardware address.
|
||||
*/
|
||||
void target_hw_addr(const hwaddress_type &new_tgt_hw_addr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the target's IP address.
|
||||
*
|
||||
* \param new_tgt_ip_addr The new target IP address.
|
||||
*/
|
||||
void target_ip_addr(ipaddress_type new_tgt_ip_addr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the hardware address format field.
|
||||
*
|
||||
* \param new_hw_addr_fmt The new hardware address format.
|
||||
*/
|
||||
void hw_addr_format(uint16_t new_hw_addr_fmt);
|
||||
|
||||
/**
|
||||
* \brief Setter for the protocol address format field.
|
||||
*
|
||||
* \param new_prot_addr_fmt The new protocol address format.
|
||||
*/
|
||||
void prot_addr_format(uint16_t new_prot_addr_fmt);
|
||||
|
||||
/**
|
||||
* \brief Setter for the hardware address length field.
|
||||
*
|
||||
* \param new_hw_addr_len The new hardware address length.
|
||||
*/
|
||||
void hw_addr_length(uint8_t new_hw_addr_len);
|
||||
|
||||
/**
|
||||
* \brief Setter for the protocol address length field.
|
||||
*
|
||||
* \param new_prot_addr_len The new protocol address length.
|
||||
*/
|
||||
void prot_addr_length(uint8_t new_prot_addr_len);
|
||||
|
||||
/**
|
||||
* \brief Setter for the ARP opcode field.
|
||||
*
|
||||
* \param new_opcode Flag enum value of the ARP opcode to set.
|
||||
*/
|
||||
void opcode(Flags new_opcode);
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Creates an ARP Request within an EthernetII PDU.
|
||||
*
|
||||
* Creates an ARP Request PDU and embeds it inside an EthernetII
|
||||
* PDU.
|
||||
*
|
||||
* \param target The target's IP address.
|
||||
* \param sender The sender's IP address.
|
||||
* \param hw_snd The sender's hardware address.
|
||||
* \return EthernetII object containing the ARP Request.
|
||||
*/
|
||||
static EthernetII make_arp_request(ipaddress_type target,
|
||||
ipaddress_type sender, const hwaddress_type &hw_snd = hwaddress_type());
|
||||
|
||||
/**
|
||||
* \brief Creates an ARP Reply within an EthernetII PDU.
|
||||
*
|
||||
* Creates an ARP Reply PDU and embeds it inside an EthernetII
|
||||
* PDU.
|
||||
*
|
||||
* \param target The target's IP address.
|
||||
* \param sender The sender's IP address.
|
||||
* \param hw_tgt The target's hardware address.
|
||||
* \param hw_snd The sender's hardware address.
|
||||
* \return EthetnetII containing the ARP Replay.
|
||||
*/
|
||||
static EthernetII make_arp_reply(ipaddress_type target,
|
||||
ipaddress_type sender, const hwaddress_type &hw_tgt = hwaddress_type(),
|
||||
const hwaddress_type &hw_snd = hwaddress_type());
|
||||
|
||||
/**
|
||||
* \brief Check wether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
ARP *clone() const {
|
||||
return new ARP(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct arphdr {
|
||||
uint16_t ar_hrd; /* format of hardware address */
|
||||
uint16_t ar_pro; /* format of protocol address */
|
||||
uint8_t ar_hln; /* length of hardware address */
|
||||
uint8_t ar_pln; /* length of protocol address */
|
||||
uint16_t ar_op; /* ARP opcode (command) */
|
||||
|
||||
/* sender hardware address */
|
||||
uint8_t ar_sha[hwaddress_type::address_size];
|
||||
/* sender IP address */
|
||||
uint32_t ar_sip;
|
||||
/* target hardware address */
|
||||
uint8_t ar_tha[hwaddress_type::address_size];
|
||||
/* target IP address */
|
||||
uint32_t ar_tip;
|
||||
} TINS_END_PACK;
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
|
||||
arphdr _arp;
|
||||
/**
|
||||
* \brief Enum which indicates the type of ARP packet.
|
||||
*/
|
||||
enum Flags {
|
||||
REQUEST = 0x0001,
|
||||
REPLY = 0x0002
|
||||
};
|
||||
}
|
||||
#endif //TINS_ARP_H
|
||||
|
||||
/**
|
||||
* \brief Extracts metadata for this protocol based on the buffer provided
|
||||
*
|
||||
* \param buffer Pointer to a buffer
|
||||
* \param total_sz Size of the buffer pointed by buffer
|
||||
*/
|
||||
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Constructs an ARP object using the provided addresses.
|
||||
*
|
||||
* ARP requests and replies can be constructed easily using
|
||||
* ARP::make_arp_request/reply static member functions.
|
||||
*
|
||||
* \sa ARP::make_arp_request
|
||||
* \sa ARP::make_arp_reply
|
||||
*
|
||||
* \param target_ip The target IP address.
|
||||
* \param sender_ip The sender IP address.
|
||||
* \param target_hw The target hardware address.
|
||||
* \param sender_hw The sender hardware address.
|
||||
*/
|
||||
ARP(ipaddress_type target_ip = ipaddress_type(),
|
||||
ipaddress_type sender_ip = ipaddress_type(),
|
||||
const hwaddress_type& target_hw = hwaddress_type(),
|
||||
const hwaddress_type& sender_hw = hwaddress_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs an ARP object from a buffer.
|
||||
*
|
||||
* If there is not enough size for an ARP header in the buffer,
|
||||
* a malformed_packet exception is thrown.
|
||||
*
|
||||
* If the buffer is bigger than the size of the ARP header,
|
||||
* then the extra data is stored in a RawPDU.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
ARP(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/* Getters */
|
||||
/**
|
||||
* \brief Getter for the sender's hardware address.
|
||||
*
|
||||
* \return The sender hardware address.
|
||||
*/
|
||||
hwaddress_type sender_hw_addr() const {
|
||||
return header_.sender_hw_address;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the sender's IP address.
|
||||
*
|
||||
* \return The sender IP address.
|
||||
*/
|
||||
ipaddress_type sender_ip_addr() const {
|
||||
return ipaddress_type(header_.sender_ip_address);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the target's hardware address.
|
||||
*
|
||||
* \return The target hardware address.
|
||||
*/
|
||||
hwaddress_type target_hw_addr() const {
|
||||
return header_.target_hw_address;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the target's IP address.
|
||||
*
|
||||
* \return The target IP address.
|
||||
*/
|
||||
ipaddress_type target_ip_addr() const {
|
||||
return ipaddress_type(header_.target_ip_address);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the hardware address format field.
|
||||
*
|
||||
* \return The hardware address format.
|
||||
*/
|
||||
uint16_t hw_addr_format() const {
|
||||
return Endian::be_to_host(header_.hw_address_format);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the protocol address format field.
|
||||
*
|
||||
* \return The protocol address format.
|
||||
*/
|
||||
uint16_t prot_addr_format() const {
|
||||
return Endian::be_to_host(header_.proto_address_format);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the hardware address length field.
|
||||
*
|
||||
* \return The hardware address length.
|
||||
*/
|
||||
uint8_t hw_addr_length() const {
|
||||
return header_.hw_address_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the protocol address length field.
|
||||
*
|
||||
* \return The protocol address length.
|
||||
*/
|
||||
uint8_t prot_addr_length() const {
|
||||
return header_.proto_address_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the ARP opcode field.
|
||||
*
|
||||
* \return The ARP opcode.
|
||||
*/
|
||||
uint16_t opcode() const {
|
||||
return Endian::be_to_host(header_.opcode);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the header size.
|
||||
* \return Returns the ARP header size.
|
||||
* \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the sender's hardware address.
|
||||
*
|
||||
* \param address The new sender hardware address.
|
||||
*/
|
||||
void sender_hw_addr(const hwaddress_type& address);
|
||||
|
||||
/**
|
||||
* \brief Setter for the sender's IP address.
|
||||
*
|
||||
* \param address The new sender IP address.
|
||||
*/
|
||||
void sender_ip_addr(ipaddress_type address);
|
||||
|
||||
/**
|
||||
* \brief Setter for the target's hardware address.
|
||||
*
|
||||
* \param address The new target hardware address.
|
||||
*/
|
||||
void target_hw_addr(const hwaddress_type& address);
|
||||
|
||||
/**
|
||||
* \brief Setter for the target's IP address.
|
||||
*
|
||||
* \param address The new target IP address.
|
||||
*/
|
||||
void target_ip_addr(ipaddress_type address);
|
||||
|
||||
/**
|
||||
* \brief Setter for the hardware address format field.
|
||||
*
|
||||
* \param format The new hardware address format.
|
||||
*/
|
||||
void hw_addr_format(uint16_t format);
|
||||
|
||||
/**
|
||||
* \brief Setter for the protocol address format field.
|
||||
*
|
||||
* \param format The new protocol address format.
|
||||
*/
|
||||
void prot_addr_format(uint16_t format);
|
||||
|
||||
/**
|
||||
* \brief Setter for the hardware address length field.
|
||||
*
|
||||
* \param length The new hardware address length.
|
||||
*/
|
||||
void hw_addr_length(uint8_t length);
|
||||
|
||||
/**
|
||||
* \brief Setter for the protocol address length field.
|
||||
*
|
||||
* \param length The new protocol address length.
|
||||
*/
|
||||
void prot_addr_length(uint8_t length);
|
||||
|
||||
/**
|
||||
* \brief Setter for the ARP opcode field.
|
||||
*
|
||||
* \param code Flag enum value of the ARP opcode to set.
|
||||
*/
|
||||
void opcode(Flags code);
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Creates an ARP Request within an EthernetII PDU.
|
||||
*
|
||||
* Creates an ARP Request PDU and embeds it inside an EthernetII
|
||||
* PDU.
|
||||
*
|
||||
* \param target The target's IP address.
|
||||
* \param sender The sender's IP address.
|
||||
* \param hw_snd The sender's hardware address.
|
||||
* \return EthernetII object containing the ARP Request.
|
||||
*/
|
||||
static EthernetII make_arp_request(ipaddress_type target,
|
||||
ipaddress_type sender,
|
||||
const hwaddress_type& hw_snd = hwaddress_type());
|
||||
|
||||
/**
|
||||
* \brief Creates an ARP Reply within an EthernetII PDU.
|
||||
*
|
||||
* Creates an ARP Reply PDU and embeds it inside an EthernetII
|
||||
* PDU.
|
||||
*
|
||||
* \param target The target's IP address.
|
||||
* \param sender The sender's IP address.
|
||||
* \param hw_tgt The target's hardware address.
|
||||
* \param hw_snd The sender's hardware address.
|
||||
* \return EthernetII object containing the ARP Reply.
|
||||
*/
|
||||
static EthernetII make_arp_reply(ipaddress_type target,
|
||||
ipaddress_type sender,
|
||||
const hwaddress_type& hw_tgt = hwaddress_type(),
|
||||
const hwaddress_type& hw_snd = hwaddress_type());
|
||||
|
||||
/**
|
||||
* \brief Check whether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
ARP* clone() const {
|
||||
return new ARP(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct arp_header {
|
||||
uint16_t hw_address_format;
|
||||
uint16_t proto_address_format;
|
||||
uint8_t hw_address_length;
|
||||
uint8_t proto_address_length;
|
||||
uint16_t opcode;
|
||||
uint8_t sender_hw_address[hwaddress_type::address_size];
|
||||
uint32_t sender_ip_address;
|
||||
uint8_t target_hw_address[hwaddress_type::address_size];
|
||||
uint32_t target_ip_address;
|
||||
} TINS_END_PACK;
|
||||
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
arp_header header_;
|
||||
};
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_ARP_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -31,333 +31,333 @@
|
||||
#define TINS_BOOTP_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include "pdu.h"
|
||||
#include "macros.h"
|
||||
#include "endianness.h"
|
||||
#include "ip_address.h"
|
||||
#include "hw_address.h"
|
||||
|
||||
#include <tins/pdu.h>
|
||||
#include <tins/macros.h>
|
||||
#include <tins/endianness.h>
|
||||
#include <tins/ip_address.h>
|
||||
#include <tins/hw_address.h>
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class BootP
|
||||
* \brief Represents a BootP PDU
|
||||
*/
|
||||
class TINS_API BootP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \class BootP
|
||||
* \brief Class representing a BootP packet.
|
||||
* The type of the IP addresses.
|
||||
*/
|
||||
class BootP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* The type of the IP addresses.
|
||||
*/
|
||||
typedef IPv4Address ipaddress_type;
|
||||
|
||||
/**
|
||||
* The type of the chaddr field.
|
||||
*/
|
||||
typedef HWAddress<16> chaddr_type;
|
||||
|
||||
/**
|
||||
* The type of the vend field.
|
||||
*/
|
||||
typedef std::vector<uint8_t> vend_type;
|
||||
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::BOOTP;
|
||||
typedef IPv4Address ipaddress_type;
|
||||
|
||||
/**
|
||||
* \brief Enum which contains the different opcodes BootP messages.
|
||||
*/
|
||||
enum OpCodes {
|
||||
BOOTREQUEST = 1,
|
||||
BOOTREPLY = 2
|
||||
};
|
||||
/**
|
||||
* The type of the chaddr field.
|
||||
*/
|
||||
typedef HWAddress<16> chaddr_type;
|
||||
|
||||
/**
|
||||
* The type of the vend field.
|
||||
*/
|
||||
typedef std::vector<uint8_t> vend_type;
|
||||
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::BOOTP;
|
||||
|
||||
/**
|
||||
* \brief Creates an instance of BootP.
|
||||
*
|
||||
* This sets the size of the vend field to 64, as the BootP RFC
|
||||
* states.
|
||||
*/
|
||||
BootP();
|
||||
|
||||
/**
|
||||
* \brief Constructs a BootP object from a buffer .
|
||||
*
|
||||
* If there's not enough size for a BootP header, then a
|
||||
* malformed_packet exception is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
* \param vend_field_size The vend field size to allocate.
|
||||
* Subclasses might use 0 to provide their own interpretation of this field.
|
||||
*/
|
||||
BootP(const uint8_t *buffer, uint32_t total_sz, uint32_t vend_field_size = 64);
|
||||
|
||||
/* Getters */
|
||||
|
||||
/**
|
||||
* \brief Getter for the opcode field.
|
||||
* \return The opcode field for this BootP PDU.
|
||||
*/
|
||||
uint8_t opcode() const { return _bootp.opcode; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the htype field.
|
||||
* \return The htype field for this BootP PDU.
|
||||
*/
|
||||
uint8_t htype() const { return _bootp.htype; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the hlen field.
|
||||
* \return The hlen field for this BootP PDU.
|
||||
*/
|
||||
uint8_t hlen() const { return _bootp.hlen; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the hops field.
|
||||
* \return The hops field for this BootP PDU.
|
||||
*/
|
||||
uint8_t hops() const { return _bootp.hops; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the xid field.
|
||||
* \return The xid field for this BootP PDU.
|
||||
*/
|
||||
uint32_t xid() const { return Endian::be_to_host(_bootp.xid); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the secs field.
|
||||
* \return The secs field for this BootP PDU.
|
||||
*/
|
||||
uint16_t secs() const { return Endian::be_to_host(_bootp.secs); }
|
||||
|
||||
/** \brief Getter for the padding field.
|
||||
* \return The padding field for this BootP PDU.
|
||||
*/
|
||||
uint16_t padding() const { return Endian::be_to_host(_bootp.padding); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the ciaddr field.
|
||||
* \return The ciaddr field for this BootP PDU.
|
||||
*/
|
||||
ipaddress_type ciaddr() const { return ipaddress_type(_bootp.ciaddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the yiaddr field.
|
||||
* \return The yiaddr field for this BootP PDU.
|
||||
*/
|
||||
ipaddress_type yiaddr() const { return ipaddress_type(_bootp.yiaddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the siaddr field.
|
||||
* \return The siaddr field for this BootP PDU.
|
||||
*/
|
||||
ipaddress_type siaddr() const { return ipaddress_type(_bootp.siaddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the giaddr field.
|
||||
* \return The giaddr field for this BootP PDU.
|
||||
*/
|
||||
ipaddress_type giaddr() const { return ipaddress_type(_bootp.giaddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the chaddr field.
|
||||
* \return The chddr field for this BootP PDU.
|
||||
*/
|
||||
chaddr_type chaddr() const { return _bootp.chaddr; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the sname field.
|
||||
* \return The sname field for this BootP PDU.
|
||||
*/
|
||||
const uint8_t *sname() const { return _bootp.sname; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the file field.
|
||||
* \return The file field for this BootP PDU.
|
||||
*/
|
||||
const uint8_t *file() const { return _bootp.file; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the vend field.
|
||||
* \return The vend field for this BootP PDU.
|
||||
*/
|
||||
const vend_type &vend() const { return _vend; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the header size.
|
||||
* \return Returns the BOOTP header size.
|
||||
* \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the opcode field.
|
||||
* \param new_opcode The opcode to be set.
|
||||
*/
|
||||
void opcode(uint8_t new_opcode);
|
||||
|
||||
/**
|
||||
* \brief Setter for the htype field.
|
||||
* \param new_htype The htype to be set.
|
||||
*/
|
||||
void htype(uint8_t new_htype);
|
||||
|
||||
/**
|
||||
* \brief Setter for the hlen field.
|
||||
* \param new_hlen The hlen to be set.
|
||||
*/
|
||||
void hlen(uint8_t new_hlen);
|
||||
|
||||
/**
|
||||
* \brief Setter for the hops field.
|
||||
* \param new_hops The hops to be set.
|
||||
*/
|
||||
void hops(uint8_t new_hops);
|
||||
|
||||
/**
|
||||
* \brief Setter for the xid field.
|
||||
* \param new_xid The xid to be set.
|
||||
*/
|
||||
void xid(uint32_t new_xid);
|
||||
|
||||
/**
|
||||
* \brief Setter for the secs field.
|
||||
* \param new_secs The secs to be set.
|
||||
*/
|
||||
void secs(uint16_t new_secs);
|
||||
|
||||
/**
|
||||
* \brief Setter for the padding field.
|
||||
* \param new_padding The padding to be set.
|
||||
*/
|
||||
void padding(uint16_t new_padding);
|
||||
|
||||
/**
|
||||
* \brief Setter for the ciaddr field.
|
||||
* \param new_ciaddr The ciaddr to be set.
|
||||
*/
|
||||
void ciaddr(ipaddress_type new_ciaddr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the yiaddr field.
|
||||
* \param new_yiaddr The yiaddr to be set.
|
||||
*/
|
||||
void yiaddr(ipaddress_type new_yiaddr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the siaddr field.
|
||||
* \param new_siaddr The siaddr to be set.
|
||||
*/
|
||||
void siaddr(ipaddress_type new_siaddr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the giaddr field.
|
||||
* \param new_giaddr The giaddr to be set.
|
||||
*/
|
||||
void giaddr(ipaddress_type new_giaddr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the chaddr field.
|
||||
* The new_chaddr pointer must be at least BOOTP::hlen() bytes long.
|
||||
* \param new_chaddr The chaddr to be set.
|
||||
*/
|
||||
template<size_t n>
|
||||
void chaddr(const HWAddress<n> &new_chaddr) {
|
||||
// Copy the new addr
|
||||
uint8_t *end = std::copy(
|
||||
new_chaddr.begin(),
|
||||
new_chaddr.begin() + std::min(n, sizeof(_bootp.chaddr)),
|
||||
_bootp.chaddr
|
||||
);
|
||||
// Fill what's left with zeros
|
||||
if(end < _bootp.chaddr + chaddr_type::address_size)
|
||||
std::fill(end, _bootp.chaddr + chaddr_type::address_size, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the sname field.
|
||||
* \param new_sname The sname to be set.
|
||||
*/
|
||||
void sname(const uint8_t *new_sname);
|
||||
|
||||
/**
|
||||
* \brief Setter for the file field.
|
||||
* \param new_file The file to be set.
|
||||
*/
|
||||
void file(const uint8_t *new_file);
|
||||
|
||||
/**
|
||||
* \brief Setter for the vend field.
|
||||
* \param new_vend The vend to be set.
|
||||
*/
|
||||
void vend(const vend_type &new_vend);
|
||||
|
||||
/**
|
||||
* \brief Check wether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* This returns true if the xid field is equal.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
BootP *clone() const {
|
||||
return new BootP(*this);
|
||||
}
|
||||
protected:
|
||||
/**
|
||||
* \brief Getter for the vend field.
|
||||
*
|
||||
* This getter can be used by subclasses to avoid copying the
|
||||
* vend field around.
|
||||
*
|
||||
* \return The vend field for this BootP PDU.
|
||||
*/
|
||||
vend_type &vend() { return _vend; }
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
private:
|
||||
/**
|
||||
* Struct that represents the Bootp datagram.
|
||||
*/
|
||||
TINS_BEGIN_PACK
|
||||
struct bootphdr {
|
||||
uint8_t opcode;
|
||||
uint8_t htype;
|
||||
uint8_t hlen;
|
||||
uint8_t hops;
|
||||
uint32_t xid;
|
||||
uint16_t secs;
|
||||
uint16_t padding;
|
||||
uint32_t ciaddr;
|
||||
uint32_t yiaddr;
|
||||
uint32_t siaddr;
|
||||
uint32_t giaddr;
|
||||
uint8_t chaddr[16];
|
||||
uint8_t sname[64];
|
||||
uint8_t file[128];
|
||||
} TINS_END_PACK;
|
||||
|
||||
bootphdr _bootp;
|
||||
vend_type _vend;
|
||||
/**
|
||||
* \brief Enum which contains the different opcodes BootP messages.
|
||||
*/
|
||||
enum OpCodes {
|
||||
BOOTREQUEST = 1,
|
||||
BOOTREPLY = 2
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Creates an instance of BootP.
|
||||
*
|
||||
* This sets the size of the vend field to 64, as the BootP RFC
|
||||
* states.
|
||||
*/
|
||||
BootP();
|
||||
|
||||
/**
|
||||
* \brief Constructs a BootP object from a buffer .
|
||||
*
|
||||
* If there's not enough size for a BootP header, then a
|
||||
* malformed_packet exception is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
* \param vend_field_size The vend field size to allocate.
|
||||
* Subclasses might use 0 to provide their own interpretation of this field.
|
||||
*/
|
||||
BootP(const uint8_t* buffer, uint32_t total_sz, uint32_t vend_field_size = 64);
|
||||
|
||||
/* Getters */
|
||||
|
||||
/**
|
||||
* \brief Getter for the opcode field.
|
||||
* \return The opcode field for this BootP PDU.
|
||||
*/
|
||||
uint8_t opcode() const { return bootp_.opcode; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the htype field.
|
||||
* \return The htype field for this BootP PDU.
|
||||
*/
|
||||
uint8_t htype() const { return bootp_.htype; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the hlen field.
|
||||
* \return The hlen field for this BootP PDU.
|
||||
*/
|
||||
uint8_t hlen() const { return bootp_.hlen; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the hops field.
|
||||
* \return The hops field for this BootP PDU.
|
||||
*/
|
||||
uint8_t hops() const { return bootp_.hops; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the xid field.
|
||||
* \return The xid field for this BootP PDU.
|
||||
*/
|
||||
uint32_t xid() const { return Endian::be_to_host(bootp_.xid); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the secs field.
|
||||
* \return The secs field for this BootP PDU.
|
||||
*/
|
||||
uint16_t secs() const { return Endian::be_to_host(bootp_.secs); }
|
||||
|
||||
/** \brief Getter for the padding field.
|
||||
* \return The padding field for this BootP PDU.
|
||||
*/
|
||||
uint16_t padding() const { return Endian::be_to_host(bootp_.padding); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the ciaddr field.
|
||||
* \return The ciaddr field for this BootP PDU.
|
||||
*/
|
||||
ipaddress_type ciaddr() const { return ipaddress_type(bootp_.ciaddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the yiaddr field.
|
||||
* \return The yiaddr field for this BootP PDU.
|
||||
*/
|
||||
ipaddress_type yiaddr() const { return ipaddress_type(bootp_.yiaddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the siaddr field.
|
||||
* \return The siaddr field for this BootP PDU.
|
||||
*/
|
||||
ipaddress_type siaddr() const { return ipaddress_type(bootp_.siaddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the giaddr field.
|
||||
* \return The giaddr field for this BootP PDU.
|
||||
*/
|
||||
ipaddress_type giaddr() const { return ipaddress_type(bootp_.giaddr); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the chaddr field.
|
||||
* \return The chddr field for this BootP PDU.
|
||||
*/
|
||||
chaddr_type chaddr() const { return bootp_.chaddr; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the sname field.
|
||||
* \return The sname field for this BootP PDU.
|
||||
*/
|
||||
const uint8_t* sname() const { return bootp_.sname; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the file field.
|
||||
* \return The file field for this BootP PDU.
|
||||
*/
|
||||
const uint8_t* file() const { return bootp_.file; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the vend field.
|
||||
* \return The vend field for this BootP PDU.
|
||||
*/
|
||||
const vend_type& vend() const { return vend_; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the header size.
|
||||
* \return Returns the BOOTP header size.
|
||||
* \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the opcode field.
|
||||
* \param code The opcode to be set.
|
||||
*/
|
||||
void opcode(uint8_t code);
|
||||
|
||||
/**
|
||||
* \brief Setter for the hardware type field.
|
||||
* \param type The hardware type field value to be set.
|
||||
*/
|
||||
void htype(uint8_t type);
|
||||
|
||||
/**
|
||||
* \brief Setter for the hlen field.
|
||||
* \param length The hlen field value to be set.
|
||||
*/
|
||||
void hlen(uint8_t length);
|
||||
|
||||
/**
|
||||
* \brief Setter for the hops field.
|
||||
* \param count The hops field value to be set.
|
||||
*/
|
||||
void hops(uint8_t count);
|
||||
|
||||
/**
|
||||
* \brief Setter for the xid field.
|
||||
* \param identifier The xid to be set.
|
||||
*/
|
||||
void xid(uint32_t identifier);
|
||||
|
||||
/**
|
||||
* \brief Setter for the secs field.
|
||||
* \param value The secs to be set.
|
||||
*/
|
||||
void secs(uint16_t value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the padding field.
|
||||
* \param value The padding to be set.
|
||||
*/
|
||||
void padding(uint16_t value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the ciaddr field.
|
||||
* \param address The ciaddr to be set.
|
||||
*/
|
||||
void ciaddr(ipaddress_type address);
|
||||
|
||||
/**
|
||||
* \brief Setter for the yiaddr field.
|
||||
* \param address The yiaddr to be set.
|
||||
*/
|
||||
void yiaddr(ipaddress_type address);
|
||||
|
||||
/**
|
||||
* \brief Setter for the siaddr field.
|
||||
* \param address The siaddr to be set.
|
||||
*/
|
||||
void siaddr(ipaddress_type address);
|
||||
|
||||
/**
|
||||
* \brief Setter for the giaddr field.
|
||||
* \param address The giaddr to be set.
|
||||
*/
|
||||
void giaddr(ipaddress_type address);
|
||||
|
||||
/**
|
||||
* \brief Setter for the chaddr field.
|
||||
* The new_chaddr pointer must be at least BOOTP::hlen() bytes long.
|
||||
* \param new_chaddr The chaddr to be set.
|
||||
*/
|
||||
template<size_t n>
|
||||
void chaddr(const HWAddress<n>& new_chaddr) {
|
||||
size_t copy_threshold = std::min(n, sizeof(bootp_.chaddr));
|
||||
for (size_t i = 0; i < copy_threshold; ++i) {
|
||||
if (i < copy_threshold) {
|
||||
bootp_.chaddr[i] = new_chaddr[i];
|
||||
}
|
||||
else {
|
||||
bootp_.chaddr[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the sname field.
|
||||
* \param new_sname The sname to be set.
|
||||
*/
|
||||
void sname(const uint8_t* new_sname);
|
||||
|
||||
/**
|
||||
* \brief Setter for the file field.
|
||||
* \param new_file The file to be set.
|
||||
*/
|
||||
void file(const uint8_t* new_file);
|
||||
|
||||
/**
|
||||
* \brief Setter for the vend field.
|
||||
* \param newvend_ The vend to be set.
|
||||
*/
|
||||
void vend(const vend_type& newvend_);
|
||||
|
||||
/**
|
||||
* \brief Check whether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* This returns true if the xid field is equal.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
BootP* clone() const {
|
||||
return new BootP(*this);
|
||||
}
|
||||
protected:
|
||||
/**
|
||||
* \brief Getter for the vend field.
|
||||
*
|
||||
* This getter can be used by subclasses to avoid copying the
|
||||
* vend field around.
|
||||
*
|
||||
* \return The vend field for this BootP PDU.
|
||||
*/
|
||||
vend_type& vend() { return vend_; }
|
||||
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* Struct that represents the Bootp datagram.
|
||||
*/
|
||||
TINS_BEGIN_PACK
|
||||
struct bootp_header {
|
||||
uint8_t opcode;
|
||||
uint8_t htype;
|
||||
uint8_t hlen;
|
||||
uint8_t hops;
|
||||
uint32_t xid;
|
||||
uint16_t secs;
|
||||
uint16_t padding;
|
||||
uint32_t ciaddr;
|
||||
uint32_t yiaddr;
|
||||
uint32_t siaddr;
|
||||
uint32_t giaddr;
|
||||
uint8_t chaddr[16];
|
||||
uint8_t sname[64];
|
||||
uint8_t file[128];
|
||||
} TINS_END_PACK;
|
||||
|
||||
private:
|
||||
bootp_header bootp_;
|
||||
vend_type vend_;
|
||||
};
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_BOOTP_H
|
||||
|
||||
@@ -2,12 +2,38 @@
|
||||
#define TINS_CONFIG_H
|
||||
|
||||
/* Define if the compiler supports basic C++11 syntax */
|
||||
#cmakedefine HAVE_CXX11
|
||||
#cmakedefine TINS_HAVE_CXX11
|
||||
|
||||
/* Have IEEE 802.11 support */
|
||||
#cmakedefine HAVE_DOT11
|
||||
#cmakedefine TINS_HAVE_DOT11
|
||||
|
||||
/* Have WPA2 decryption library */
|
||||
#cmakedefine HAVE_WPA2_DECRYPTION
|
||||
#cmakedefine TINS_HAVE_WPA2_DECRYPTION
|
||||
|
||||
/* Use pcap_sendpacket to send l2 packets */
|
||||
#cmakedefine TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
|
||||
/* Have TCPIP classes */
|
||||
#cmakedefine TINS_HAVE_TCPIP
|
||||
|
||||
/* Have TCP ACK tracking */
|
||||
#cmakedefine TINS_HAVE_ACK_TRACKER
|
||||
|
||||
/* Have TCP stream custom data */
|
||||
#cmakedefine TINS_HAVE_TCP_STREAM_CUSTOM_DATA
|
||||
|
||||
/* Have GCC builtin swap */
|
||||
#cmakedefine TINS_HAVE_GCC_BUILTIN_SWAP
|
||||
|
||||
/* Have WPA2Decrypter callbacks */
|
||||
#cmakedefine TINS_HAVE_WPA2_CALLBACKS
|
||||
|
||||
/* Have libpcap */
|
||||
#cmakedefine TINS_HAVE_PCAP
|
||||
|
||||
/* Version macros */
|
||||
#define TINS_VERSION_MAJOR ${TINS_VERSION_MAJOR}
|
||||
#define TINS_VERSION_MINOR ${TINS_VERSION_MINOR}
|
||||
#define TINS_VERSION_PATCH ${TINS_VERSION_PATCH}
|
||||
|
||||
#endif // TINS_CONFIG_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -31,130 +31,133 @@
|
||||
#define TINS_CONSTANTS_H
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \brief Constants used in protocols.
|
||||
*/
|
||||
namespace Constants {
|
||||
/** \cond */
|
||||
struct IP {
|
||||
/** \endcond */
|
||||
enum e {
|
||||
PROTO_IP = 0, /* Dummy protocol for TCP. */
|
||||
PROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */
|
||||
PROTO_ICMP = 1, /* Internet Control Message Protocol. */
|
||||
PROTO_IGMP = 2, /* Internet Group Management Protocol. */
|
||||
PROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94). */
|
||||
PROTO_TCP = 6, /* Transmission Control Protocol. */
|
||||
PROTO_EGP = 8, /* Exterior Gateway Protocol. */
|
||||
PROTO_PUP = 12, /* PUP protocol. */
|
||||
PROTO_UDP = 17, /* User Datagram Protocol. */
|
||||
PROTO_IDP = 22, /* XNS IDP protocol. */
|
||||
PROTO_TP = 29, /* SO Transport Protocol Class 4. */
|
||||
PROTO_DCCP = 33, /* Datagram Congestion Control Protocol. */
|
||||
PROTO_IPV6 = 41, /* IPv6 header. */
|
||||
PROTO_ROUTING = 43, /* IPv6 routing header. */
|
||||
PROTO_FRAGMENT = 44, /* IPv6 fragmentation header. */
|
||||
PROTO_RSVP = 46, /* Reservation Protocol. */
|
||||
PROTO_GRE = 47, /* General Routing Encapsulation. */
|
||||
PROTO_ESP = 50, /* encapsulating security payload. */
|
||||
PROTO_AH = 51, /* authentication header. */
|
||||
PROTO_ICMPV6 = 58, /* ICMPv6. */
|
||||
PROTO_NONE = 59, /* IPv6 no next header. */
|
||||
PROTO_DSTOPTS = 60, /* IPv6 destination options. */
|
||||
PROTO_MTP = 92, /* Multicast Transport Protocol. */
|
||||
PROTO_ENCAP = 98, /* Encapsulation Header. */
|
||||
PROTO_PIM = 103, /* Protocol Independent Multicast. */
|
||||
PROTO_COMP = 108, /* Compression Header Protocol. */
|
||||
PROTO_SCTP = 132, /* Stream Control Transmission Protocol. */
|
||||
PROTO_UDPLITE = 136, /* UDP-Lite protocol. */
|
||||
PROTO_RAW = 255 /* Raw IP packets. */
|
||||
};
|
||||
};
|
||||
|
||||
struct Ethernet {
|
||||
enum e {
|
||||
UNKNOWN = 0,
|
||||
//~ PUP = 0x0200, /* Xerox PUP */
|
||||
SPRITE = 0x0500, /* Sprite */
|
||||
IP = 0x0800, /* IP */
|
||||
ARP = 0x0806, /* Address resolution */
|
||||
REVARP = 0x8035, /* Reverse ARP */
|
||||
AT = 0x809B, /* AppleTalk protocol */
|
||||
AARP = 0x80F3, /* AppleTalk ARP */
|
||||
VLAN = 0x8100, /* IEEE 802.1Q VLAN tagging */
|
||||
IPX = 0x8137, /* IPX */
|
||||
IPV6 = 0x86dd, /* IP protocol version 6 */
|
||||
PPPOED = 0x8863, /* PPPoE Discovery */
|
||||
PPPOES = 0x8864, /* PPPoE Session */
|
||||
EAPOL = 0x888e, /* EAPOL */
|
||||
LOOPBACK = 0x9000 /* used to test interfaces */
|
||||
};
|
||||
};
|
||||
|
||||
struct ARP {
|
||||
enum e {
|
||||
NETROM = 0, /* From KA9Q: NET/ROM pseudo. */
|
||||
ETHER = 1, /* Ethernet 10/100Mbps. */
|
||||
EETHER = 2, /* Experimental Ethernet. */
|
||||
AX25 = 3, /* AX.25 Level 2. */
|
||||
PRONET = 4, /* PROnet token ring. */
|
||||
CHAOS = 5, /* Chaosnet. */
|
||||
IEEE802 = 6, /* IEEE 802.2 Ethernet/TR/TB. */
|
||||
ARCNET = 7, /* ARCnet. */
|
||||
APPLETLK = 8, /* APPLEtalk. */
|
||||
DLCI = 15, /* Frame Relay DLCI. */
|
||||
ATM = 19, /* ATM. */
|
||||
METRICOM = 23, /* Metricom STRIP (new IANA id). */
|
||||
IEEE1394 = 24, /* IEEE 1394 IPv4 - RFC 2734. */
|
||||
EUI64 = 27, /* EUI-64. */
|
||||
INFINIBAND = 32, /* InfiniBand. */
|
||||
SLIP = 256,
|
||||
CSLIP = 257,
|
||||
SLIP6 = 258,
|
||||
CSLIP6 = 259,
|
||||
RSRVD = 260, /* Notional KISS type. */
|
||||
ADAPT = 264,
|
||||
ROSE = 270,
|
||||
X25 = 271, /* CCITT X.25. */
|
||||
HWX25 = 272, /* Boards with X.25 in firmware. */
|
||||
PPP = 512,
|
||||
CISCO = 513, /* Cisco HDLC. */
|
||||
HDLC = CISCO,
|
||||
LAPB = 516, /* LAPB. */
|
||||
DDCMP = 517, /* Digital's DDCMP. */
|
||||
RAWHDLC = 518, /* Raw HDLC. */
|
||||
TUNNEL = 768, /* IPIP tunnel. */
|
||||
TUNNEL6 = 769, /* IPIP6 tunnel. */
|
||||
FRAD = 770, /* Frame Relay Access Device. */
|
||||
SKIP = 771, /* SKIP vif. */
|
||||
LOOPBACK = 772, /* Loopback device. */
|
||||
LOCALTLK = 773, /* Localtalk device. */
|
||||
FDDI = 774, /* Fiber Distributed Data Interface. */
|
||||
BIF = 775, /* AP1000 BIF. */
|
||||
SIT = 776, /* sit0 device - IPv6-in-IPv4. */
|
||||
IPDDP = 777, /* IP-in-DDP tunnel. */
|
||||
IPGRE = 778, /* GRE over IP. */
|
||||
PIMREG = 779, /* PIMSM register interface. */
|
||||
HIPPI = 780, /* High Performance Parallel I'face. */
|
||||
ASH = 781, /* (Nexus Electronics) Ash. */
|
||||
ECONET = 782, /* Acorn Econet. */
|
||||
IRDA = 783, /* Linux-IrDA. */
|
||||
FCPP = 784, /* Point to point fibrechanel. */
|
||||
FCAL = 785, /* Fibrechanel arbitrated loop. */
|
||||
FCPL = 786, /* Fibrechanel public loop. */
|
||||
FCFABRIC = 787, /* Fibrechanel fabric. */
|
||||
IEEE802_TR = 800, /* Magic type ident for TR. */
|
||||
IEEE80211 = 801, /* IEEE 802.11. */
|
||||
IEEE80211_PRISM = 802, /* IEEE 802.11 + Prism2 header. */
|
||||
IEEE80211_RADIOTAP = 803, /* IEEE 802.11 + radiotap header. */
|
||||
IEEE802154 = 804, /* IEEE 802.15.4 header. */
|
||||
IEEE802154_PHY = 805, /* IEEE 802.15.4 PHY header. */
|
||||
VOID_TYPE = 0xFFFF, /* Void type, nothing is known. */
|
||||
NONE = 0xFFFE /* Zero header length. */
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Constants used in protocols.
|
||||
*/
|
||||
namespace Constants {
|
||||
/** \cond */
|
||||
struct IP {
|
||||
/** \endcond */
|
||||
enum e {
|
||||
PROTO_IP = 0, // Dummy protocol for TCP.
|
||||
PROTO_HOPOPTS = 0, // IPv6 Hop-by-Hop options.
|
||||
PROTO_ICMP = 1, // Internet Control Message Protocol.
|
||||
PROTO_IGMP = 2, // Internet Group Management Protocol.
|
||||
PROTO_IPIP = 4, // IPIP tunnels (older KA9Q tunnels use 94).
|
||||
PROTO_TCP = 6, // Transmission Control Protocol.
|
||||
PROTO_EGP = 8, // Exterior Gateway Protocol.
|
||||
PROTO_PUP = 12, // PUP protocol.
|
||||
PROTO_UDP = 17, // User Datagram Protocol.
|
||||
PROTO_IDP = 22, // XNS IDP protocol.
|
||||
PROTO_TP = 29, // SO Transport Protocol Class 4.
|
||||
PROTO_DCCP = 33, // Datagram Congestion Control Protocol.
|
||||
PROTO_IPV6 = 41, // IPv6 header.
|
||||
PROTO_ROUTING = 43, // IPv6 routing header.
|
||||
PROTO_FRAGMENT = 44, // IPv6 fragmentation header.
|
||||
PROTO_RSVP = 46, // Reservation Protocol.
|
||||
PROTO_GRE = 47, // General Routing Encapsulation.
|
||||
PROTO_ESP = 50, // encapsulating security payload.
|
||||
PROTO_AH = 51, // authentication header.
|
||||
PROTO_ICMPV6 = 58, // ICMPv6.
|
||||
PROTO_NONE = 59, // IPv6 no next header.
|
||||
PROTO_DSTOPTS = 60, // IPv6 destination options.
|
||||
PROTO_MTP = 92, // Multicast Transport Protocol.
|
||||
PROTO_ENCAP = 98, // Encapsulation Header.
|
||||
PROTO_PIM = 103, // Protocol Independent Multicast.
|
||||
PROTO_COMP = 108, // Compression Header Protocol.
|
||||
PROTO_SCTP = 132, // Stream Control Transmission Protocol.
|
||||
PROTO_UDPLITE = 136, // UDP-Lite protocol.
|
||||
PROTO_RAW = 255 // Raw IP packets.
|
||||
};
|
||||
};
|
||||
|
||||
struct Ethernet {
|
||||
enum e {
|
||||
UNKNOWN = 0,
|
||||
SPRITE = 0x0500, // Sprite
|
||||
IP = 0x0800, // IP
|
||||
ARP = 0x0806, // Address resolution
|
||||
MPLS = 0x8847, // MPLS
|
||||
REVARP = 0x8035, // Reverse ARP
|
||||
AT = 0x809B, // AppleTalk protocol
|
||||
AARP = 0x80F3, // AppleTalk ARP
|
||||
VLAN = 0x8100, // IEEE 802.1Q VLAN tagging
|
||||
QINQ = 0x88a8, // IEEE 802.1ad VLAN tagging
|
||||
OLD_QINQ = 0x9100, // IEEE 802.1ad VLAN tagging (old, deprecated, value)
|
||||
IPX = 0x8137, // IPX
|
||||
IPV6 = 0x86dd, // IP protocol version 6
|
||||
PPPOED = 0x8863, // PPPoE Discovery
|
||||
PPPOES = 0x8864, // PPPoE Session
|
||||
EAPOL = 0x888e, // EAPOL
|
||||
LOOPBACK = 0x9000 // used to test interfaces
|
||||
};
|
||||
};
|
||||
|
||||
struct ARP {
|
||||
enum e {
|
||||
NETROM = 0, // From KA9Q: NET/ROM pseudo.
|
||||
ETHER = 1, // Ethernet 10/100Mbps.
|
||||
EETHER = 2, // Experimental Ethernet.
|
||||
AX25 = 3, // AX.25 Level 2.
|
||||
PRONET = 4, // PROnet token ring.
|
||||
CHAOS = 5, // Chaosnet.
|
||||
IEEE802 = 6, // IEEE 802.2 Ethernet/TR/TB.
|
||||
ARCNET = 7, // ARCnet.
|
||||
APPLETLK = 8, // APPLEtalk.
|
||||
DLCI = 15, // Frame Relay DLCI.
|
||||
ATM = 19, // ATM.
|
||||
METRICOM = 23, // Metricom STRIP (new IANA id).
|
||||
IEEE1394 = 24, // IEEE 1394 IPv4 - RFC 2734.
|
||||
EUI64 = 27, // EUI-64.
|
||||
INFINIBAND = 32, // InfiniBand.
|
||||
SLIP = 256,
|
||||
CSLIP = 257,
|
||||
SLIP6 = 258,
|
||||
CSLIP6 = 259,
|
||||
RSRVD = 260, // Notional KISS type.
|
||||
ADAPT = 264,
|
||||
ROSE = 270,
|
||||
X25 = 271, // CCITT X.25.
|
||||
HWX25 = 272, // Boards with X.25 in firmware.
|
||||
PPP = 512,
|
||||
CISCO = 513, // Cisco HDLC.
|
||||
HDLC = CISCO,
|
||||
LAPB = 516, // LAPB.
|
||||
DDCMP = 517, // Digital's DDCMP.
|
||||
RAWHDLC = 518, // Raw HDLC.
|
||||
TUNNEL = 768, // IPIP tunnel.
|
||||
TUNNEL6 = 769, // IPIP6 tunnel.
|
||||
FRAD = 770, // Frame Relay Access Device.
|
||||
SKIP = 771, // SKIP vif.
|
||||
LOOPBACK = 772, // Loopback device.
|
||||
LOCALTLK = 773, // Localtalk device.
|
||||
FDDI = 774, // Fiber Distributed Data Interface.
|
||||
BIF = 775, // AP1000 BIF.
|
||||
SIT = 776, // sit0 device - IPv6-in-IPv4.
|
||||
IPDDP = 777, // IP-in-DDP tunnel.
|
||||
IPGRE = 778, // GRE over IP.
|
||||
PIMREG = 779, // PIMSM register interface.
|
||||
HIPPI = 780, // High Performance Parallel I'face.
|
||||
ASH = 781, // (Nexus Electronics) Ash.
|
||||
ECONET = 782, // Acorn Econet.
|
||||
IRDA = 783, // Linux-IrDA.
|
||||
FCPP = 784, // Point to point fibrechanel.
|
||||
FCAL = 785, // Fibrechanel arbitrated loop.
|
||||
FCPL = 786, // Fibrechanel public loop.
|
||||
FCFABRIC = 787, // Fibrechanel fabric.
|
||||
IEEE802_TR = 800, // Magic type ident for TR.
|
||||
IEEE80211 = 801, // IEEE 802.11.
|
||||
IEEE80211_PRISM = 802, // IEEE 802.11 + Prism2 header.
|
||||
IEEE80211_RADIOTAP = 803, // IEEE 802.11 + radiotap header.
|
||||
IEEE802154 = 804, // IEEE 802.15.4 header.
|
||||
IEEE802154_PHY = 805, // IEEE 802.15.4 PHY header.
|
||||
VOID_TYPE = 0xFFFF, // Void type, nothing is known.
|
||||
NONE = 0xFFFE // Zero header length.
|
||||
};
|
||||
};
|
||||
|
||||
} // Constants
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_CONSTANTS_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -27,389 +27,510 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <tins/config.h>
|
||||
|
||||
#if !defined(TINS_CRYPTO_H) && defined(HAVE_DOT11)
|
||||
#if !defined(TINS_CRYPTO_H) && defined(TINS_HAVE_DOT11)
|
||||
#define TINS_CRYPTO_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include "utils.h"
|
||||
#include "snap.h"
|
||||
#include "rawpdu.h"
|
||||
#include "handshake_capturer.h"
|
||||
#ifdef TINS_HAVE_WPA2_CALLBACKS
|
||||
#include <functional>
|
||||
#endif // TINS_HAVE_WPA2_CALLBACKS
|
||||
#include <tins/macros.h>
|
||||
#include <tins/handshake_capturer.h>
|
||||
|
||||
namespace Tins {
|
||||
|
||||
class PDU;
|
||||
class Dot11;
|
||||
class Dot11Data;
|
||||
class SNAP;
|
||||
class RawPDU;
|
||||
|
||||
namespace Crypto {
|
||||
/**
|
||||
* \cond
|
||||
*/
|
||||
struct RC4Key;
|
||||
#ifdef HAVE_WPA2_DECRYPTION
|
||||
namespace WPA2 {
|
||||
class invalid_handshake : public std::exception {
|
||||
public:
|
||||
const char *what() const throw() {
|
||||
return "invalid handshake";
|
||||
}
|
||||
};
|
||||
class SessionKeys {
|
||||
public:
|
||||
typedef Internals::byte_array<80> ptk_type;
|
||||
typedef Internals::byte_array<32> pmk_type;
|
||||
|
||||
SessionKeys();
|
||||
SessionKeys(const RSNHandshake &hs, const pmk_type &pmk);
|
||||
SNAP *decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const;
|
||||
private:
|
||||
SNAP *ccmp_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const;
|
||||
SNAP *tkip_decrypt_unicast(const Dot11Data &dot11, RawPDU &raw) const;
|
||||
RC4Key generate_rc4_key(const Dot11Data &dot11, const RawPDU &raw) const;
|
||||
|
||||
ptk_type ptk;
|
||||
bool is_ccmp;
|
||||
};
|
||||
|
||||
class SupplicantData {
|
||||
public:
|
||||
typedef HWAddress<6> address_type;
|
||||
typedef SessionKeys::pmk_type pmk_type;
|
||||
|
||||
SupplicantData(const std::string &psk, const std::string &ssid);
|
||||
|
||||
const pmk_type &pmk() const;
|
||||
private:
|
||||
pmk_type pmk_;
|
||||
};
|
||||
}
|
||||
#endif // HAVE_WPA2_DECRYPTION
|
||||
#ifdef TINS_HAVE_WPA2_DECRYPTION
|
||||
namespace WPA2 {
|
||||
|
||||
/**
|
||||
* \brief Class that represents the keys used to decrypt a session.
|
||||
*/
|
||||
class TINS_API SessionKeys {
|
||||
public:
|
||||
/**
|
||||
* \endcond
|
||||
* The size of the Pairwise Master Key.
|
||||
*/
|
||||
static const size_t PMK_SIZE;
|
||||
|
||||
/**
|
||||
* \brief RC4 Key abstraction.
|
||||
* The size of the Pairwise Transient Key.
|
||||
*/
|
||||
struct RC4Key {
|
||||
static const size_t data_size = 256;
|
||||
|
||||
/**
|
||||
* \brief Initializes the key using the provided iterator range.
|
||||
*
|
||||
* \param start The start of the range.
|
||||
* \param end The end of the range.
|
||||
*/
|
||||
template<typename ForwardIterator>
|
||||
RC4Key(ForwardIterator start, ForwardIterator end);
|
||||
|
||||
/**
|
||||
* The actual key data.
|
||||
*/
|
||||
uint8_t data[data_size];
|
||||
};
|
||||
static const size_t PTK_SIZE;
|
||||
|
||||
/**
|
||||
* \brief Decrypts WEP-encrypted traffic.
|
||||
* The type used to hold the PTK (this has to be PTK_SIZE bytes long).
|
||||
*/
|
||||
class WEPDecrypter {
|
||||
public:
|
||||
typedef HWAddress<6> address_type;
|
||||
typedef std::vector<uint8_t> ptk_type;
|
||||
|
||||
/**
|
||||
* The type used to hold the PMK (this has to be PMK_SIZE bytes long).
|
||||
*/
|
||||
typedef std::vector<uint8_t> pmk_type;
|
||||
|
||||
/**
|
||||
* \brief Constructs a WEPDecrypter object.
|
||||
*/
|
||||
WEPDecrypter();
|
||||
|
||||
/**
|
||||
* \brief Adds a decryption password.
|
||||
*
|
||||
* \param addr The access point's BSSID.
|
||||
* \param password The password which will be used to decrypt
|
||||
* packets sent from and to the AP identifier by the BSSID addr.
|
||||
*/
|
||||
void add_password(const address_type &addr, const std::string &password);
|
||||
|
||||
/**
|
||||
* \brief Removes a decryption password
|
||||
*
|
||||
* \param addr The BSSID of the access point.
|
||||
*/
|
||||
void remove_password(const address_type &addr);
|
||||
|
||||
/**
|
||||
* \brief Decrypts the provided PDU.
|
||||
*
|
||||
* A Dot11Data PDU is looked up inside the provided PDU chain.
|
||||
* If no such PDU exists or there is no password associated
|
||||
* with the Dot11 packet's BSSID, then the PDU is left intact.
|
||||
*
|
||||
* Otherwise, the packet is decrypted using the given password.
|
||||
* If the CRC found after decrypting is invalid, false is
|
||||
* returned.
|
||||
*
|
||||
* \return false if no decryption was performed or decryption
|
||||
* failed, true otherwise.
|
||||
*/
|
||||
bool decrypt(PDU &pdu);
|
||||
private:
|
||||
typedef std::map<address_type, std::string> passwords_type;
|
||||
|
||||
PDU *decrypt(RawPDU &raw, const std::string &password);
|
||||
|
||||
passwords_type passwords;
|
||||
std::vector<uint8_t> key_buffer;
|
||||
};
|
||||
|
||||
#ifdef HAVE_WPA2_DECRYPTION
|
||||
/**
|
||||
* \brief Decrypts WPA2-encrypted traffic.
|
||||
* Default constructs a SessionKeys object.
|
||||
*/
|
||||
SessionKeys();
|
||||
|
||||
/**
|
||||
* \brief Constructs an instance using the provided PTK and a flag
|
||||
* indicating whether it should use ccmp.
|
||||
*
|
||||
* This class takes valid PSK and SSID tuples, captures client handshakes,
|
||||
* and decrypts their traffic afterwards.
|
||||
* \param ptk The PTK to use.
|
||||
* \param is_ccmp Indicates whether to use CCMP to decrypt this traffic.
|
||||
*/
|
||||
class WPA2Decrypter {
|
||||
public:
|
||||
/*
|
||||
* \brief The type used to store Dot11 addresses.
|
||||
*/
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
/**
|
||||
* \brief Adds an access points's information.
|
||||
*
|
||||
* This associates an SSID with a PSK, and allows the decryption of
|
||||
* any BSSIDs that broadcast the same SSID.
|
||||
*
|
||||
* The decrypter will inspect beacon frames, looking for SSID tags
|
||||
* that contain the given SSID.
|
||||
*
|
||||
* Note that using this overload, the decryption of data frames and
|
||||
* handshake capturing will be disabled until any access point
|
||||
* broadcasts the provided SSID(this shouldn't take long at all).
|
||||
* If this is not the desired behaviour, then you should check out
|
||||
* the ovther add_ap_data overload.
|
||||
*
|
||||
* \param psk The PSK associated with the SSID.
|
||||
* \param ssid The network's SSID.
|
||||
*/
|
||||
void add_ap_data(const std::string &psk, const std::string &ssid);
|
||||
|
||||
/**
|
||||
* \brief Adds a access points's information, including its BSSID.
|
||||
*
|
||||
* This overload can be used if the BSSID associated with this SSID is
|
||||
* known beforehand. The addr parameter indicates which specific BSSID
|
||||
* is associated to the SSID.
|
||||
*
|
||||
* Note that if any other access point broadcasts the provided SSID,
|
||||
* it will be taken into account as well.
|
||||
*
|
||||
* \param psk The PSK associated with this SSID.
|
||||
* \param ssid The network's SSID.
|
||||
* \param addr The access point's BSSID.
|
||||
*/
|
||||
void add_ap_data(const std::string &psk, const std::string &ssid, const address_type &addr);
|
||||
|
||||
/**
|
||||
* \brief Decrypts the provided PDU.
|
||||
*
|
||||
* A Dot11Data PDU is looked up inside the provided PDU chain.
|
||||
* If no such PDU exists or no PSK was associated with the SSID
|
||||
* broadcasted by the Dot11 packet's BSSID, or no EAPOL handshake
|
||||
* was captured for the client involved in the communication,
|
||||
* then the PDU is left intact.
|
||||
*
|
||||
* Otherwise, the packet is decrypted using the generated PTK.
|
||||
* If the resulting MIC is invalid, then the packet is left intact.
|
||||
*
|
||||
* \return false if no decryption was performed, or the decryption
|
||||
* failed, true otherwise.
|
||||
*/
|
||||
bool decrypt(PDU &pdu);
|
||||
private:
|
||||
typedef std::map<std::string, WPA2::SupplicantData> pmks_map;
|
||||
typedef std::map<address_type, WPA2::SupplicantData> bssids_map;
|
||||
typedef std::pair<address_type, address_type> addr_pair;
|
||||
typedef std::map<addr_pair, WPA2::SessionKeys> keys_map;
|
||||
|
||||
void try_add_keys(const Dot11Data &dot11, const RSNHandshake &hs);
|
||||
addr_pair make_addr_pair(const address_type &addr1, const address_type &addr2) {
|
||||
return (addr1 < addr2) ?
|
||||
std::make_pair(addr1, addr2) :
|
||||
std::make_pair(addr2, addr1);
|
||||
}
|
||||
addr_pair extract_addr_pair(const Dot11Data &dot11);
|
||||
addr_pair extract_addr_pair_dst(const Dot11Data &dot11);
|
||||
bssids_map::const_iterator find_ap(const Dot11Data &dot11);
|
||||
void add_access_point(const std::string &ssid, const address_type &addr);
|
||||
|
||||
RSNHandshakeCapturer capturer;
|
||||
pmks_map pmks;
|
||||
bssids_map aps;
|
||||
keys_map keys;
|
||||
};
|
||||
#endif // HAVE_WPA2_DECRYPTION
|
||||
SessionKeys(const ptk_type& ptk, bool is_ccmp);
|
||||
|
||||
/**
|
||||
* \brief Pluggable decrypter object which can be used to decrypt
|
||||
* data on sniffing sessions.
|
||||
*
|
||||
* This class holds a decrypter object and a functor, and implements
|
||||
* a suitable operator() to be used on BaseSniffer::sniff_loop, which
|
||||
* decrypts packets and forwards them to the given functor.
|
||||
* \brief Constructs an instance using a handshake and a PMK.
|
||||
*
|
||||
* This will internally construct the PTK from the input parameters.
|
||||
*
|
||||
* \param hs The handshake to use.
|
||||
* \param pmk The PMK to use.
|
||||
*/
|
||||
template<typename Functor, typename Decrypter>
|
||||
class DecrypterProxy {
|
||||
public:
|
||||
/**
|
||||
* The type of the functor object.
|
||||
*/
|
||||
typedef Functor functor_type;
|
||||
|
||||
/**
|
||||
* The type of the decrypter object.
|
||||
*/
|
||||
typedef Decrypter decrypter_type;
|
||||
|
||||
/**
|
||||
* \brief Constructs an object from a functor and a decrypter.
|
||||
* \param func The functor to be used to forward decrypted
|
||||
* packets.
|
||||
* \param decrypter The decrypter which will be used to decrypt
|
||||
* packets
|
||||
*/
|
||||
DecrypterProxy(const functor_type &func,
|
||||
const decrypter_type &decr = decrypter_type());
|
||||
|
||||
/**
|
||||
* \brief Retrieves a reference to the decrypter object.
|
||||
*/
|
||||
decrypter_type &decrypter();
|
||||
|
||||
/**
|
||||
* \brief Retrieves a const reference to the decrypter object.
|
||||
*/
|
||||
const decrypter_type &decrypter() const;
|
||||
|
||||
/**
|
||||
* \brief The operator() which decrypts packets and forwards
|
||||
* them to the functor.
|
||||
*/
|
||||
bool operator() (PDU &pdu);
|
||||
private:
|
||||
Functor functor_;
|
||||
decrypter_type decrypter_;
|
||||
};
|
||||
SessionKeys(const RSNHandshake& hs, const pmk_type& pmk);
|
||||
|
||||
/**
|
||||
* \brief Performs RC4 encription/decryption of the given byte range,
|
||||
* using the provided key.
|
||||
*
|
||||
* The decrypted range will be copied to the OutputIterator provided.
|
||||
*
|
||||
* \param start The beginning of the range.
|
||||
* \param start The end of the range.
|
||||
* \param key The key to be used.
|
||||
* \param output The iterator in which to write the output.
|
||||
* \brief Decrypts a unicast packet.
|
||||
*
|
||||
* \param dot11 The encrypted packet to decrypt.
|
||||
* \param raw The raw layer on the packet to decrypt.
|
||||
* \return A SNAP layer containing the decrypted traffic or a null pointer
|
||||
* if decryption failed.
|
||||
*/
|
||||
template<typename ForwardIterator, typename OutputIterator>
|
||||
void rc4(ForwardIterator start, ForwardIterator end, RC4Key &key, OutputIterator output);
|
||||
SNAP* decrypt_unicast(const Dot11Data& dot11, RawPDU& raw) const;
|
||||
|
||||
/**
|
||||
* \brief Gets the PTK for this session keys.
|
||||
* \return The Pairwise Transcient Key.
|
||||
*/
|
||||
const ptk_type& get_ptk() const;
|
||||
|
||||
/**
|
||||
* \brief Indicates whether CCMP is used to decrypt packets
|
||||
* /return true iff CCMP is used.
|
||||
*/
|
||||
bool uses_ccmp() const;
|
||||
private:
|
||||
SNAP* ccmp_decrypt_unicast(const Dot11Data& dot11, RawPDU& raw) const;
|
||||
SNAP* tkip_decrypt_unicast(const Dot11Data& dot11, RawPDU& raw) const;
|
||||
|
||||
ptk_type ptk_;
|
||||
bool is_ccmp_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Represents a WPA2 supplicant's data.
|
||||
*
|
||||
* Objects of this class can be given the pre-shared key and the SSID
|
||||
* of some access point, and this will generate the Pairwise Master Key
|
||||
* from those parameters.
|
||||
*/
|
||||
class TINS_API SupplicantData {
|
||||
public:
|
||||
/**
|
||||
* The type used to store the PMK.
|
||||
*/
|
||||
typedef SessionKeys::pmk_type pmk_type;
|
||||
|
||||
/**
|
||||
* \brief Wrapper function to create a DecrypterProxy using a
|
||||
* WEPDecrypter as the Decrypter template parameter.
|
||||
*
|
||||
* \param functor The functor to be forwarded to the DecrypterProxy
|
||||
* constructor.
|
||||
* \brief Constructs a SupplicantData.
|
||||
* \param psk The pre-shared key.
|
||||
* \param ssid The access point's SSID.
|
||||
*/
|
||||
template<typename Functor>
|
||||
DecrypterProxy<Functor, WEPDecrypter> make_wep_decrypter_proxy(const Functor &functor);
|
||||
|
||||
#ifdef HAVE_WPA2_DECRYPTION
|
||||
SupplicantData(const std::string& psk, const std::string& ssid);
|
||||
|
||||
/**
|
||||
* \brief Wrapper function to create a DecrypterProxy using a
|
||||
* WPA2Decrypter as the Decrypter template parameter.
|
||||
*
|
||||
* \param functor The functor to be forwarded to the DecrypterProxy
|
||||
* constructor.
|
||||
* \brief Getter for the PMK.
|
||||
* \return The generated PMK.
|
||||
*/
|
||||
template<typename Functor>
|
||||
DecrypterProxy<Functor, WPA2Decrypter> make_wpa2_decrypter_proxy(const Functor &functor) {
|
||||
return DecrypterProxy<Functor, WPA2Decrypter>(functor);
|
||||
}
|
||||
#endif // HAVE_WPA2_DECRYPTION
|
||||
|
||||
// Implementation section
|
||||
|
||||
// DecrypterProxy
|
||||
|
||||
template<typename Functor, typename Decrypter>
|
||||
DecrypterProxy<Functor, Decrypter>::DecrypterProxy(
|
||||
const functor_type &func, const decrypter_type& decr)
|
||||
: functor_(func), decrypter_(decr)
|
||||
{
|
||||
|
||||
}
|
||||
const pmk_type& pmk() const;
|
||||
|
||||
template<typename Functor, typename Decrypter>
|
||||
typename DecrypterProxy<Functor, Decrypter>::decrypter_type &
|
||||
DecrypterProxy<Functor, Decrypter>::decrypter()
|
||||
{
|
||||
return decrypter_;
|
||||
}
|
||||
/**
|
||||
* \brief Getter for the SSID
|
||||
* \return The access point's SSID
|
||||
*/
|
||||
const std::string& ssid() const;
|
||||
private:
|
||||
pmk_type pmk_;
|
||||
std::string ssid_;
|
||||
};
|
||||
|
||||
template<typename Functor, typename Decrypter>
|
||||
const typename DecrypterProxy<Functor, Decrypter>::decrypter_type &
|
||||
DecrypterProxy<Functor, Decrypter>::decrypter() const
|
||||
{
|
||||
return decrypter_;
|
||||
}
|
||||
} // WPA2
|
||||
#endif // TINS_HAVE_WPA2_DECRYPTION
|
||||
|
||||
template<typename Functor, typename Decrypter>
|
||||
bool DecrypterProxy<Functor, Decrypter>::operator() (PDU &pdu)
|
||||
{
|
||||
return decrypter_.decrypt(pdu) ? functor_(pdu) : true;
|
||||
}
|
||||
|
||||
template<typename Functor>
|
||||
DecrypterProxy<Functor, WEPDecrypter> make_wep_decrypter_proxy(const Functor &functor)
|
||||
{
|
||||
return DecrypterProxy<Functor, WEPDecrypter>(functor);
|
||||
}
|
||||
/**
|
||||
* \brief Decrypts WEP-encrypted traffic.
|
||||
*/
|
||||
class TINS_API WEPDecrypter {
|
||||
public:
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
// RC4 stuff
|
||||
/**
|
||||
* \brief Constructs a WEPDecrypter object.
|
||||
*/
|
||||
WEPDecrypter();
|
||||
|
||||
template<typename ForwardIterator>
|
||||
RC4Key::RC4Key(ForwardIterator start, ForwardIterator end) {
|
||||
for(size_t i = 0; i < data_size; ++i)
|
||||
data[i] = i;
|
||||
size_t j = 0;
|
||||
ForwardIterator iter = start;
|
||||
for(size_t i = 0; i < data_size; ++i) {
|
||||
j = (j + data[i] + *iter++) % 256;
|
||||
if(iter == end)
|
||||
iter = start;
|
||||
std::swap(data[i], data[j]);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* \brief Adds a decryption password.
|
||||
*
|
||||
* \param addr The access point's BSSID.
|
||||
* \param password The password which will be used to decrypt
|
||||
* packets sent from and to the AP identifier by the BSSID addr.
|
||||
*/
|
||||
void add_password(const address_type& addr, const std::string& password);
|
||||
|
||||
template<typename ForwardIterator, typename OutputIterator>
|
||||
void rc4(ForwardIterator start, ForwardIterator end, RC4Key &key, OutputIterator output) {
|
||||
size_t i = 0, j = 0;
|
||||
while(start != end) {
|
||||
i = (i + 1) % RC4Key::data_size;
|
||||
j = (j + key.data[i]) % RC4Key::data_size;
|
||||
std::swap(key.data[i], key.data[j]);
|
||||
*output++ = *start++ ^ key.data[(key.data[i] + key.data[j]) % RC4Key::data_size];
|
||||
}
|
||||
/**
|
||||
* \brief Removes a decryption password
|
||||
*
|
||||
* \param addr The BSSID of the access point.
|
||||
*/
|
||||
void remove_password(const address_type& addr);
|
||||
|
||||
/**
|
||||
* \brief Decrypts the provided PDU.
|
||||
*
|
||||
* A Dot11Data PDU is looked up inside the provided PDU chain.
|
||||
* If no such PDU exists or there is no password associated
|
||||
* with the Dot11 packet's BSSID, then the PDU is left intact.
|
||||
*
|
||||
* Otherwise, the packet is decrypted using the given password.
|
||||
* If the CRC found after decrypting is invalid, false is
|
||||
* returned.
|
||||
*
|
||||
* \return false if no decryption was performed or decryption
|
||||
* failed, true otherwise.
|
||||
*/
|
||||
bool decrypt(PDU& pdu);
|
||||
private:
|
||||
typedef std::map<address_type, std::string> passwords_type;
|
||||
|
||||
PDU* decrypt(RawPDU& raw, const std::string& password);
|
||||
|
||||
passwords_type passwords_;
|
||||
std::vector<uint8_t> key_buffer_;
|
||||
};
|
||||
|
||||
#ifdef TINS_HAVE_WPA2_DECRYPTION
|
||||
/**
|
||||
* \brief Decrypts WPA2-encrypted traffic.
|
||||
*
|
||||
* This class takes valid PSK and SSID tuples, captures client handshakes,
|
||||
* and decrypts their traffic afterwards.
|
||||
*/
|
||||
class TINS_API WPA2Decrypter {
|
||||
public:
|
||||
/*
|
||||
* \brief The type used to store Dot11 addresses.
|
||||
*/
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
/**
|
||||
* \brief Represents a pair of mac addresses.
|
||||
*
|
||||
* This is used to identify a host and the access point to which
|
||||
* it is connected. The first element in the pair will always de
|
||||
* lower or equal than the second one, so that given any host and
|
||||
* the access point it's connected to, we can uniquely identify
|
||||
* it with an address pair.
|
||||
*/
|
||||
typedef std::pair<address_type, address_type> addr_pair;
|
||||
|
||||
/**
|
||||
* \brief Maps an address pair to the session keys.
|
||||
*
|
||||
* This type associates an address pair (host, access point) with the
|
||||
* session keys, as generated using the packets seen on a handshake.
|
||||
*
|
||||
* \sa addr_pair
|
||||
*/
|
||||
typedef std::map<addr_pair, WPA2::SessionKeys> keys_map;
|
||||
|
||||
#ifdef TINS_HAVE_WPA2_CALLBACKS
|
||||
|
||||
/**
|
||||
* \brief The type used to store the callback type used when a new access
|
||||
* point is found.
|
||||
*
|
||||
* The first argument to the function will be the access point's SSID and
|
||||
* the second one its BSSID.
|
||||
*/
|
||||
typedef std::function<void(const std::string&,
|
||||
const address_type&)> ap_found_callback_type;
|
||||
|
||||
/**
|
||||
* The type used to store the callback type used when a new handshake
|
||||
* is captured.
|
||||
*
|
||||
* The first argument to the function will be the access point's SSID and
|
||||
* the second one its BSSID. The third argument will be the client's hardware
|
||||
* address.
|
||||
*/
|
||||
typedef std::function<void(const std::string&,
|
||||
const address_type&,
|
||||
const address_type&)> handshake_captured_callback_type;
|
||||
|
||||
#endif // TINS_HAVE_WPA2_CALLBACKS
|
||||
|
||||
/**
|
||||
* \brief Adds an access points's information.
|
||||
*
|
||||
* This associates an SSID with a PSK, and allows the decryption of
|
||||
* any BSSIDs that broadcast the same SSID.
|
||||
*
|
||||
* The decrypter will inspect beacon frames, looking for SSID tags
|
||||
* that contain the given SSID.
|
||||
*
|
||||
* Note that using this overload, the decryption of data frames and
|
||||
* handshake capturing will be disabled until any access point
|
||||
* broadcasts the provided SSID(this shouldn't take long at all).
|
||||
* If this is not the desired behaviour, then you should check out
|
||||
* the ovther add_ap_data overload.
|
||||
*
|
||||
* \param psk The PSK associated with the SSID.
|
||||
* \param ssid The network's SSID.
|
||||
*/
|
||||
void add_ap_data(const std::string& psk, const std::string& ssid);
|
||||
|
||||
/**
|
||||
* \brief Adds a access points's information, including its BSSID.
|
||||
*
|
||||
* This overload can be used if the BSSID associated with this SSID is
|
||||
* known beforehand. The addr parameter indicates which specific BSSID
|
||||
* is associated to the SSID.
|
||||
*
|
||||
* Note that if any other access point broadcasts the provided SSID,
|
||||
* it will be taken into account as well.
|
||||
*
|
||||
* \param psk The PSK associated with this SSID.
|
||||
* \param ssid The network's SSID.
|
||||
* \param addr The access point's BSSID.
|
||||
*/
|
||||
void add_ap_data(const std::string& psk,
|
||||
const std::string& ssid,
|
||||
const address_type& addr);
|
||||
|
||||
/**
|
||||
* \brief Explicitly add decryption keys.
|
||||
*
|
||||
* This method associates a pair (host, access point) with the given decryption keys.
|
||||
* All encrypted packets sent between the given addresses will be decrypted using the
|
||||
* provided keys.
|
||||
*
|
||||
* This method shouldn't normally be required. The WPA2Decrypter will be waiting for
|
||||
* handshakes and will automatically extract the session keys, decrypting all
|
||||
* encrypted packets with them. You should only use this method if for some reason
|
||||
* you know the actual keys being used (because you checked and stored the keys_map
|
||||
* somewhere).
|
||||
*
|
||||
* The actual order of the addresses doesn't matter, this method will make sure
|
||||
* they're sorted.
|
||||
*
|
||||
* \param addresses The address pair (host, access point) to associate.
|
||||
* \param session_keys The keys to use when decrypting messages sent between the
|
||||
* given addresses.
|
||||
*/
|
||||
void add_decryption_keys(const addr_pair& addresses,
|
||||
const WPA2::SessionKeys& session_keys);
|
||||
|
||||
/**
|
||||
* \brief Decrypts the provided PDU.
|
||||
*
|
||||
* A Dot11Data PDU is looked up inside the provided PDU chain.
|
||||
* If no such PDU exists or no PSK was associated with the SSID
|
||||
* broadcasted by the Dot11 packet's BSSID, or no EAPOL handshake
|
||||
* was captured for the client involved in the communication,
|
||||
* then the PDU is left intact.
|
||||
*
|
||||
* Otherwise, the packet is decrypted using the generated PTK.
|
||||
* If the resulting MIC is invalid, then the packet is left intact.
|
||||
*
|
||||
* \return false if no decryption was performed, or the decryption
|
||||
* failed, true otherwise.
|
||||
*/
|
||||
bool decrypt(PDU& pdu);
|
||||
|
||||
#ifdef TINS_HAVE_WPA2_CALLBACKS
|
||||
/**
|
||||
* \brief Sets the handshake captured callback
|
||||
*
|
||||
* This callback will be executed every time a new handshake is captured.
|
||||
*
|
||||
* \sa handshake_captured_callback_type
|
||||
* \param callback The new callback to be set
|
||||
*/
|
||||
void handshake_captured_callback(const handshake_captured_callback_type& callback);
|
||||
|
||||
/**
|
||||
* \brief Sets the access point found callback
|
||||
*
|
||||
* This callback will be executed every time a new access point is found, that's
|
||||
* advertising an SSID added when calling add_ap_data.
|
||||
*
|
||||
* \sa ap_found_callback_type
|
||||
* \param callback The new callback to be set
|
||||
*/
|
||||
void ap_found_callback(const ap_found_callback_type& callback);
|
||||
|
||||
#endif // TINS_HAVE_WPA2_CALLBACKS
|
||||
|
||||
/**
|
||||
* \brief Getter for the keys on this decrypter
|
||||
*
|
||||
* The returned map will be populated every time a new, complete, handshake
|
||||
* is captured.
|
||||
*
|
||||
* \return The WPA2Decrypter keys map.
|
||||
*/
|
||||
const keys_map& get_keys() const;
|
||||
private:
|
||||
typedef std::map<std::string, WPA2::SupplicantData> pmks_map;
|
||||
typedef std::map<address_type, WPA2::SupplicantData> bssids_map;
|
||||
|
||||
void try_add_keys(const Dot11Data& dot11, const RSNHandshake& hs);
|
||||
addr_pair make_addr_pair(const address_type& addr1, const address_type& addr2) {
|
||||
return (addr1 < addr2) ?
|
||||
std::make_pair(addr1, addr2) :
|
||||
std::make_pair(addr2, addr1);
|
||||
}
|
||||
addr_pair extract_addr_pair(const Dot11Data& dot11);
|
||||
addr_pair extract_addr_pair_dst(const Dot11Data& dot11);
|
||||
bssids_map::const_iterator find_ap(const Dot11Data& dot11);
|
||||
void add_access_point(const std::string& ssid, const address_type& addr);
|
||||
|
||||
RSNHandshakeCapturer capturer_;
|
||||
pmks_map pmks_;
|
||||
bssids_map aps_;
|
||||
keys_map keys_;
|
||||
#ifdef TINS_HAVE_WPA2_CALLBACKS
|
||||
handshake_captured_callback_type handshake_captured_callback_;
|
||||
ap_found_callback_type ap_found_callback_;
|
||||
#endif // TINS_HAVE_WPA2_CALLBACKS
|
||||
};
|
||||
#endif // TINS_HAVE_WPA2_DECRYPTION
|
||||
|
||||
/**
|
||||
* \brief Pluggable decrypter object which can be used to decrypt
|
||||
* data on sniffing sessions.
|
||||
*
|
||||
* This class holds a decrypter object and a functor, and implements
|
||||
* a suitable operator() to be used on BaseSniffer::sniff_loop, which
|
||||
* decrypts packets and forwards them to the given functor.
|
||||
*/
|
||||
template<typename Functor, typename Decrypter>
|
||||
class DecrypterProxy {
|
||||
public:
|
||||
/**
|
||||
* The type of the functor object.
|
||||
*/
|
||||
typedef Functor functor_type;
|
||||
|
||||
/**
|
||||
* The type of the decrypter object.
|
||||
*/
|
||||
typedef Decrypter decrypter_type;
|
||||
|
||||
/**
|
||||
* \brief Constructs an object from a functor and a decrypter.
|
||||
* \param func The functor to be used to forward decrypted
|
||||
* packets.
|
||||
* \param decrypter The decrypter which will be used to decrypt
|
||||
* packets
|
||||
*/
|
||||
DecrypterProxy(const functor_type& func,
|
||||
const decrypter_type& decr = decrypter_type());
|
||||
|
||||
/**
|
||||
* \brief Retrieves a reference to the decrypter object.
|
||||
*/
|
||||
decrypter_type& decrypter();
|
||||
|
||||
/**
|
||||
* \brief Retrieves a const reference to the decrypter object.
|
||||
*/
|
||||
const decrypter_type& decrypter() const;
|
||||
|
||||
/**
|
||||
* \brief The operator() which decrypts packets and forwards
|
||||
* them to the functor.
|
||||
*/
|
||||
bool operator() (PDU& pdu);
|
||||
private:
|
||||
Functor functor_;
|
||||
decrypter_type decrypter_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Wrapper function to create a DecrypterProxy using a
|
||||
* WEPDecrypter as the Decrypter template parameter.
|
||||
*
|
||||
* \param functor The functor to be forwarded to the DecrypterProxy
|
||||
* constructor.
|
||||
*/
|
||||
template<typename Functor>
|
||||
DecrypterProxy<Functor, WEPDecrypter> make_wep_decrypter_proxy(const Functor& functor);
|
||||
|
||||
#ifdef TINS_HAVE_WPA2_DECRYPTION
|
||||
/**
|
||||
* \brief Wrapper function to create a DecrypterProxy using a
|
||||
* WPA2Decrypter as the Decrypter template parameter.
|
||||
*
|
||||
* \param functor The functor to be forwarded to the DecrypterProxy
|
||||
* constructor.
|
||||
*/
|
||||
template<typename Functor>
|
||||
DecrypterProxy<Functor, WPA2Decrypter> make_wpa2_decrypter_proxy(const Functor& functor) {
|
||||
return DecrypterProxy<Functor, WPA2Decrypter>(functor);
|
||||
}
|
||||
#endif // TINS_HAVE_WPA2_DECRYPTION
|
||||
|
||||
// Implementation section
|
||||
|
||||
// DecrypterProxy
|
||||
|
||||
template<typename Functor, typename Decrypter>
|
||||
DecrypterProxy<Functor, Decrypter>::DecrypterProxy(const functor_type& func,
|
||||
const decrypter_type& decr)
|
||||
: functor_(func), decrypter_(decr) {
|
||||
|
||||
}
|
||||
|
||||
template<typename Functor, typename Decrypter>
|
||||
typename DecrypterProxy<Functor, Decrypter>::decrypter_type &
|
||||
DecrypterProxy<Functor, Decrypter>::decrypter() {
|
||||
return decrypter_;
|
||||
}
|
||||
|
||||
template<typename Functor, typename Decrypter>
|
||||
const typename DecrypterProxy<Functor, Decrypter>::decrypter_type &
|
||||
DecrypterProxy<Functor, Decrypter>::decrypter() const {
|
||||
return decrypter_;
|
||||
}
|
||||
|
||||
template<typename Functor, typename Decrypter>
|
||||
bool DecrypterProxy<Functor, Decrypter>::operator() (PDU& pdu) {
|
||||
return decrypter_.decrypt(pdu) ? functor_(pdu) : true;
|
||||
}
|
||||
|
||||
template<typename Functor>
|
||||
DecrypterProxy<Functor, WEPDecrypter> make_wep_decrypter_proxy(const Functor& functor) {
|
||||
return DecrypterProxy<Functor, WEPDecrypter>(functor);
|
||||
}
|
||||
|
||||
} // Crypto
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_CRYPTO_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -30,7 +30,7 @@
|
||||
#ifndef TINS_CXXSTD_H
|
||||
#define TINS_CXXSTD_H
|
||||
|
||||
#include <memory>
|
||||
#include <tins/config.h>
|
||||
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
#define TINS_CXXSTD_GCC_FIX 1
|
||||
@@ -38,20 +38,15 @@
|
||||
#define TINS_CXXSTD_GCC_FIX 0
|
||||
#endif // __GXX_EXPERIMENTAL_CXX0X__
|
||||
|
||||
#ifndef TINS_IS_CXX11
|
||||
#if !defined(TINS_IS_CXX11) && defined(TINS_HAVE_CXX11)
|
||||
#define TINS_IS_CXX11 (__cplusplus > 199711L || TINS_CXXSTD_GCC_FIX == 1 || _MSC_VER >= 1800)
|
||||
#elif !defined(TINS_IS_CXX11)
|
||||
#define TINS_IS_CXX11 0
|
||||
#endif // TINS_IS_CXX11
|
||||
|
||||
namespace Tins{
|
||||
namespace Internals {
|
||||
template<typename T>
|
||||
struct smart_ptr {
|
||||
#if TINS_IS_CXX11
|
||||
typedef std::unique_ptr<T> type;
|
||||
#else
|
||||
typedef std::auto_ptr<T> type;
|
||||
#endif
|
||||
};
|
||||
template<class T> void unused(const T&) { }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -41,6 +41,7 @@ class Dot3;
|
||||
class SLL;
|
||||
class Loopback;
|
||||
class PPI;
|
||||
class IP;
|
||||
|
||||
/**
|
||||
* \struct DataLinkType
|
||||
@@ -73,6 +74,7 @@ TINS_MAKE_DATA_LINK_TYPE(Loopback, DLT_LOOP)
|
||||
TINS_MAKE_DATA_LINK_TYPE(PPI, DLT_PPI)
|
||||
TINS_MAKE_DATA_LINK_TYPE(Dot11, DLT_IEEE802_11)
|
||||
TINS_MAKE_DATA_LINK_TYPE(RadioTap, DLT_IEEE802_11_RADIO)
|
||||
TINS_MAKE_DATA_LINK_TYPE(IP, DLT_RAW)
|
||||
|
||||
#undef TINS_MAKE_DATA_LINK_TYPE
|
||||
|
||||
|
||||
106
include/tins/detail/address_helpers.h
Normal file
106
include/tins/detail/address_helpers.h
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_ADDRESS_HELPERS_H
|
||||
#define TINS_ADDRESS_HELPERS_H
|
||||
|
||||
#include <tins/hw_address.h>
|
||||
|
||||
/**
|
||||
* \cond
|
||||
*/
|
||||
namespace Tins {
|
||||
|
||||
class IPv4Address;
|
||||
class IPv6Address;
|
||||
|
||||
namespace Internals {
|
||||
|
||||
template<typename T>
|
||||
bool increment_buffer(T& addr) {
|
||||
typename T::iterator it = addr.end() - 1;
|
||||
while (it >= addr.begin() && *it == 0xff) {
|
||||
*it = 0;
|
||||
--it;
|
||||
}
|
||||
// reached end
|
||||
if (it < addr.begin()) {
|
||||
return true;
|
||||
}
|
||||
(*it)++;
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool decrement_buffer(T& addr) {
|
||||
typename T::iterator it = addr.end() - 1;
|
||||
while (it >= addr.begin() && *it == 0) {
|
||||
*it = 0xff;
|
||||
--it;
|
||||
}
|
||||
// reached end
|
||||
if (it < addr.begin()) {
|
||||
return true;
|
||||
}
|
||||
(*it)--;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool increment(IPv4Address& addr);
|
||||
bool increment(IPv6Address& addr);
|
||||
bool decrement(IPv4Address& addr);
|
||||
bool decrement(IPv6Address& addr);
|
||||
template<size_t n>
|
||||
bool increment(HWAddress<n>& addr) {
|
||||
return increment_buffer(addr);
|
||||
}
|
||||
template<size_t n>
|
||||
bool decrement(HWAddress<n>& addr) {
|
||||
return decrement_buffer(addr);
|
||||
}
|
||||
|
||||
IPv4Address last_address_from_mask(IPv4Address addr, IPv4Address mask);
|
||||
IPv6Address last_address_from_mask(IPv6Address addr, const IPv6Address& mask);
|
||||
template<size_t n>
|
||||
HWAddress<n> last_address_from_mask(HWAddress<n> addr, const HWAddress<n>& mask) {
|
||||
typename HWAddress<n>::iterator addr_iter = addr.begin();
|
||||
for (typename HWAddress<n>::const_iterator it = mask.begin(); it != mask.end(); ++it, ++addr_iter) {
|
||||
*addr_iter = *addr_iter | ~*it;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
} // Internals
|
||||
} // Tins
|
||||
|
||||
/**
|
||||
* \endcond
|
||||
*/
|
||||
|
||||
#endif // TINS_ADDRESS_HELPERS_H
|
||||
61
include/tins/detail/icmp_extension_helpers.h
Normal file
61
include/tins/detail/icmp_extension_helpers.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_ICMP_EXTENSION_HELPERS_H
|
||||
#define TINS_ICMP_EXTENSION_HELPERS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* \cond
|
||||
*/
|
||||
namespace Tins {
|
||||
|
||||
class PDU;
|
||||
class ICMPExtensionsStructure;
|
||||
|
||||
namespace Memory {
|
||||
class InputMemoryStream;
|
||||
} // Memory
|
||||
|
||||
namespace Internals {
|
||||
|
||||
uint32_t get_padded_icmp_inner_pdu_size(const PDU* inner_pdu, uint32_t pad_alignment);
|
||||
void try_parse_icmp_extensions(Memory::InputMemoryStream& stream, uint32_t payload_length,
|
||||
ICMPExtensionsStructure& extensions);
|
||||
|
||||
|
||||
} // Internals
|
||||
} // Tins
|
||||
|
||||
/**
|
||||
* \endcond
|
||||
*/
|
||||
|
||||
#endif // TINS_ICMP_EXTENSION_HELPERS_H
|
||||
70
include/tins/detail/pdu_helpers.h
Normal file
70
include/tins/detail/pdu_helpers.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_PDU_HELPERS_H
|
||||
#define TINS_PDU_HELPERS_H
|
||||
|
||||
#include <tins/constants.h>
|
||||
#include <tins/config.h>
|
||||
#include <tins/pdu.h>
|
||||
|
||||
/**
|
||||
* \cond
|
||||
*/
|
||||
|
||||
namespace Tins {
|
||||
namespace Internals {
|
||||
|
||||
PDU* pdu_from_flag(Constants::Ethernet::e flag, const uint8_t* buffer,
|
||||
uint32_t size, bool rawpdu_on_no_match = true);
|
||||
PDU* pdu_from_flag(Constants::IP::e flag, const uint8_t* buffer,
|
||||
uint32_t size, bool rawpdu_on_no_match = true);
|
||||
#ifdef TINS_HAVE_PCAP
|
||||
PDU* pdu_from_dlt_flag(int flag, const uint8_t* buffer,
|
||||
uint32_t size, bool rawpdu_on_no_match = true);
|
||||
#endif // TINS_HAVE_PCAP
|
||||
PDU* pdu_from_flag(PDU::PDUType type, const uint8_t* buffer, uint32_t size);
|
||||
|
||||
Constants::Ethernet::e pdu_flag_to_ether_type(PDU::PDUType flag);
|
||||
PDU::PDUType ether_type_to_pdu_flag(Constants::Ethernet::e flag);
|
||||
Constants::IP::e pdu_flag_to_ip_type(PDU::PDUType flag);
|
||||
PDU::PDUType ip_type_to_pdu_flag(Constants::IP::e flag);
|
||||
|
||||
inline bool is_dot3(const uint8_t* ptr, size_t sz) {
|
||||
return (sz >= 13 && ptr[12] < 8);
|
||||
}
|
||||
|
||||
} // Internals
|
||||
} // Tins
|
||||
|
||||
/**
|
||||
* \endcond
|
||||
*/
|
||||
|
||||
#endif // TINS_PDU_HELPERS_H
|
||||
49
include/tins/detail/sequence_number_helpers.h
Normal file
49
include/tins/detail/sequence_number_helpers.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_SEQUENCE_NUMBER_HELPERS_H
|
||||
#define TINS_SEQUENCE_NUMBER_HELPERS_H
|
||||
|
||||
#include <stdint.h>
|
||||
/**
|
||||
* \cond
|
||||
*/
|
||||
namespace Tins {
|
||||
namespace Internals {
|
||||
|
||||
// Compares sequence numbers as defined by RFC 1982.
|
||||
int seq_compare(uint32_t seq1, uint32_t seq2);
|
||||
|
||||
} // namespace Internals
|
||||
} // namespace Tins
|
||||
/**
|
||||
* \endcond
|
||||
*/
|
||||
|
||||
#endif // TINS_SEQUENCE_NUMBER_HELPERS_H
|
||||
51
include/tins/detail/smart_ptr.h
Normal file
51
include/tins/detail/smart_ptr.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_SMART_PTR_H
|
||||
#define TINS_SMART_PTR_H
|
||||
|
||||
#include <memory>
|
||||
#include <tins/cxxstd.h>
|
||||
|
||||
namespace Tins {
|
||||
namespace Internals {
|
||||
|
||||
template<typename T>
|
||||
struct smart_ptr {
|
||||
#if TINS_IS_CXX11
|
||||
typedef std::unique_ptr<T> type;
|
||||
#else
|
||||
typedef std::auto_ptr<T> type;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // Internals
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_SMART_PTR_H
|
||||
127
include/tins/detail/type_traits.h
Normal file
127
include/tins/detail/type_traits.h
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_TYPE_TRAITS_H
|
||||
#define TINS_TYPE_TRAITS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <tins/cxxstd.h>
|
||||
#if TINS_IS_CXX11
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#endif
|
||||
|
||||
namespace Tins {
|
||||
namespace Internals {
|
||||
/**
|
||||
* \cond
|
||||
*/
|
||||
|
||||
template<bool, typename T = void>
|
||||
struct enable_if {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct enable_if<false, T> {
|
||||
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct type_to_type {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_unsigned_integral {
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is_unsigned_integral<uint8_t> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is_unsigned_integral<uint16_t> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is_unsigned_integral<uint32_t> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is_unsigned_integral<uint64_t> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
#if TINS_IS_CXX11 && !defined(_MSC_VER)
|
||||
|
||||
// Template metaprogramming trait to determine if a functor can accept another parameter as an argument
|
||||
template <typename T, typename P, typename=void>
|
||||
struct accepts_type : std::false_type { };
|
||||
|
||||
template <typename T, typename P>
|
||||
struct accepts_type<T, P,
|
||||
typename std::enable_if<
|
||||
std::is_same< decltype( std::declval<T>()(std::declval<P>()) ), bool>::value
|
||||
>::type
|
||||
> : std::true_type { };
|
||||
|
||||
// use enable_if to invoke the Packet&& version of the sniff_loop handler if possible - otherwise fail to old behavior
|
||||
template <typename Functor, typename Packet>
|
||||
bool invoke_loop_cb(Functor& f, Packet& p,
|
||||
typename std::enable_if<accepts_type<Functor, Packet>::value, bool>::type* = 0) {
|
||||
return f(std::move(p));
|
||||
}
|
||||
|
||||
template <typename Functor, typename Packet>
|
||||
bool invoke_loop_cb(Functor& f, Packet& p,
|
||||
typename std::enable_if<!accepts_type<Functor, Packet>::value && accepts_type<Functor, Packet&>::value, bool>::type* = 0) {
|
||||
return f(p);
|
||||
}
|
||||
|
||||
template <typename Functor, typename Packet>
|
||||
bool invoke_loop_cb(Functor& f, Packet& p,
|
||||
typename std::enable_if<!accepts_type<Functor, Packet>::value && !accepts_type<Functor, Packet&>::value, bool>::type* = 0) {
|
||||
return f(*p.pdu());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \endcond
|
||||
*/
|
||||
|
||||
} // Internals
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_TYPE_TRAITS_H
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -30,481 +30,503 @@
|
||||
#ifndef TINS_DHCP_H
|
||||
#define TINS_DHCP_H
|
||||
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "bootp.h"
|
||||
#include "pdu_option.h"
|
||||
#include "cxxstd.h"
|
||||
#include <tins/bootp.h>
|
||||
#include <tins/macros.h>
|
||||
#include <tins/pdu_option.h>
|
||||
#include <tins/cxxstd.h>
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \class DHCP
|
||||
* \brief Represents the DHCP PDU.
|
||||
*
|
||||
* This class represents a DHCP PDU. It contains helpers methods
|
||||
* which make it easy to set/get specific option values.
|
||||
*
|
||||
* Note that when adding options, the "End" option is not added
|
||||
* automatically, so you will have to add it yourself.
|
||||
*
|
||||
* Options can be retrieved easily from DHCP PDUs:
|
||||
*
|
||||
* \code
|
||||
* // Sniff a packet from somewhere
|
||||
* DHCP dhcp = get_dhcp_from_somewhere();
|
||||
*
|
||||
* // This retrieves the Domain Name Servers option and converts
|
||||
* // it to a std::vector<IPv4Address>. Note that if this option
|
||||
* // is not present, an option_not_found exception is thrown.
|
||||
* for(const auto& address : dhcp.domain_name_servers()) {
|
||||
* // address is an ip
|
||||
* }
|
||||
*
|
||||
* \endcode
|
||||
|
||||
/**
|
||||
* \class DHCP
|
||||
* \brief Represents the DHCP PDU.
|
||||
*
|
||||
* This class represents a DHCP PDU. It contains helpers methods
|
||||
* which make it easy to set/get specific option values.
|
||||
*
|
||||
* Note that when adding options, the "End" option is not added
|
||||
* automatically, so you will have to add it yourself.
|
||||
*
|
||||
* Options can be retrieved easily from DHCP PDUs:
|
||||
*
|
||||
* \code
|
||||
* // Sniff a packet from somewhere
|
||||
* DHCP dhcp = get_dhcp_from_somewhere();
|
||||
*
|
||||
* // This retrieves the Domain Name Servers option and converts
|
||||
* // it to a std::vector<IPv4Address>. Note that if this option
|
||||
* // is not present, an option_not_found exception is thrown.
|
||||
* for(const auto& address : dhcp.domain_name_servers()) {
|
||||
* // address is an ip
|
||||
* }
|
||||
*
|
||||
* \endcode
|
||||
*/
|
||||
class TINS_API DHCP : public BootP {
|
||||
public:
|
||||
/**
|
||||
* This PDU's flag.
|
||||
*/
|
||||
class DHCP : public BootP {
|
||||
public:
|
||||
/**
|
||||
* This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DHCP;
|
||||
static const PDU::PDUType pdu_flag = PDU::DHCP;
|
||||
|
||||
/**
|
||||
* DHCP flags.
|
||||
*/
|
||||
enum Flags {
|
||||
DISCOVER = 1,
|
||||
OFFER = 2,
|
||||
REQUEST = 3,
|
||||
DECLINE = 4,
|
||||
ACK = 5,
|
||||
NAK = 6,
|
||||
RELEASE = 7,
|
||||
INFORM = 8
|
||||
};
|
||||
|
||||
/**
|
||||
* DHCP flags.
|
||||
*/
|
||||
enum Flags {
|
||||
DISCOVER = 1,
|
||||
OFFER = 2,
|
||||
REQUEST = 3,
|
||||
DECLINE = 4,
|
||||
ACK = 5,
|
||||
NAK = 6,
|
||||
RELEASE = 7,
|
||||
INFORM = 8
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief DHCP options enum.
|
||||
*/
|
||||
enum OptionTypes {
|
||||
PAD,
|
||||
SUBNET_MASK,
|
||||
TIME_OFFSET,
|
||||
ROUTERS,
|
||||
TIME_SERVERS,
|
||||
NAME_SERVERS,
|
||||
DOMAIN_NAME_SERVERS,
|
||||
LOG_SERVERS,
|
||||
COOKIE_SERVERS,
|
||||
LPR_SERVERS,
|
||||
IMPRESS_SERVERS,
|
||||
RESOURCE_LOCATION_SERVERS,
|
||||
HOST_NAME,
|
||||
BOOT_SIZE,
|
||||
MERIT_DUMP,
|
||||
DOMAIN_NAME,
|
||||
SWAP_SERVER,
|
||||
ROOT_PATH,
|
||||
EXTENSIONS_PATH,
|
||||
IP_FORWARDING,
|
||||
NON_LOCAL_SOURCE_ROUTING,
|
||||
POLICY_FILTER,
|
||||
MAX_DGRAM_REASSEMBLY,
|
||||
DEFAULT_IP_TTL,
|
||||
PATH_MTU_AGING_TIMEOUT,
|
||||
PATH_MTU_PLATEAU_TABLE,
|
||||
INTERFACE_MTU,
|
||||
ALL_SUBNETS_LOCAL,
|
||||
BROADCAST_ADDRESS,
|
||||
PERFORM_MASK_DISCOVERY,
|
||||
MASK_SUPPLIER,
|
||||
ROUTER_DISCOVERY,
|
||||
ROUTER_SOLICITATION_ADDRESS,
|
||||
STATIC_ROUTES,
|
||||
TRAILER_ENCAPSULATION,
|
||||
ARP_CACHE_TIMEOUT,
|
||||
IEEE802_3_ENCAPSULATION,
|
||||
DEFAULT_TCP_TTL,
|
||||
TCP_KEEPALIVE_INTERVAL,
|
||||
TCP_KEEPALIVE_GARBAGE,
|
||||
NIS_DOMAIN,
|
||||
NIS_SERVERS,
|
||||
NTP_SERVERS,
|
||||
VENDOR_ENCAPSULATED_OPTIONS,
|
||||
NETBIOS_NAME_SERVERS,
|
||||
NETBIOS_DD_SERVER,
|
||||
NETBIOS_NODE_TYPE,
|
||||
NETBIOS_SCOPE,
|
||||
FONT_SERVERS,
|
||||
X_DISPLAY_MANAGER,
|
||||
DHCP_REQUESTED_ADDRESS,
|
||||
DHCP_LEASE_TIME,
|
||||
DHCP_OPTION_OVERLOAD,
|
||||
DHCP_MESSAGE_TYPE,
|
||||
DHCP_SERVER_IDENTIFIER,
|
||||
DHCP_PARAMETER_REQUEST_LIST,
|
||||
DHCP_MESSAGE,
|
||||
DHCP_MAX_MESSAGE_SIZE,
|
||||
DHCP_RENEWAL_TIME,
|
||||
DHCP_REBINDING_TIME,
|
||||
VENDOR_CLASS_IDENTIFIER,
|
||||
DHCP_CLIENT_IDENTIFIER,
|
||||
NWIP_DOMAIN_NAME,
|
||||
NWIP_SUBOPTIONS,
|
||||
USER_CLASS = 77,
|
||||
FQDN = 81,
|
||||
DHCP_AGENT_OPTIONS = 82,
|
||||
SUBNET_SELECTION = 118,
|
||||
AUTHENTICATE = 210,
|
||||
END = 255
|
||||
};
|
||||
|
||||
/**
|
||||
* The DHCP option type.
|
||||
*/
|
||||
typedef PDUOption<uint8_t, DHCP> option;
|
||||
|
||||
/**
|
||||
* The type used to store the DHCP options.
|
||||
*/
|
||||
typedef std::list<option> options_type;
|
||||
|
||||
/**
|
||||
* \brief Creates an instance of DHCP.
|
||||
*
|
||||
* This sets the hwtype and hlen fields to match the ethernet
|
||||
* type and length.
|
||||
*/
|
||||
DHCP();
|
||||
|
||||
/**
|
||||
* \brief Constructs a DHCP object from a buffer.
|
||||
*
|
||||
* If there is not enough size for a BootP header, or any of
|
||||
* the TLV options contains an invalid size field, then a
|
||||
* malformed_packet exception is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
DHCP(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief DHCP options enum.
|
||||
*/
|
||||
enum OptionTypes {
|
||||
PAD,
|
||||
SUBNET_MASK,
|
||||
TIME_OFFSET,
|
||||
ROUTERS,
|
||||
TIME_SERVERS,
|
||||
NAME_SERVERS,
|
||||
DOMAIN_NAME_SERVERS,
|
||||
LOG_SERVERS,
|
||||
COOKIE_SERVERS,
|
||||
LPR_SERVERS,
|
||||
IMPRESS_SERVERS,
|
||||
RESOURCE_LOCATION_SERVERS,
|
||||
HOST_NAME,
|
||||
BOOT_SIZE,
|
||||
MERIT_DUMP,
|
||||
DOMAIN_NAME,
|
||||
SWAP_SERVER,
|
||||
ROOT_PATH,
|
||||
EXTENSIONS_PATH,
|
||||
IP_FORWARDING,
|
||||
NON_LOCAL_SOURCE_ROUTING,
|
||||
POLICY_FILTER,
|
||||
MAX_DGRAM_REASSEMBLY,
|
||||
DEFAULT_IP_TTL,
|
||||
PATH_MTU_AGING_TIMEOUT,
|
||||
PATH_MTU_PLATEAU_TABLE,
|
||||
INTERFACE_MTU,
|
||||
ALL_SUBNETS_LOCAL,
|
||||
BROADCAST_ADDRESS,
|
||||
PERFORM_MASK_DISCOVERY,
|
||||
MASK_SUPPLIER,
|
||||
ROUTER_DISCOVERY,
|
||||
ROUTER_SOLICITATION_ADDRESS,
|
||||
STATIC_ROUTES,
|
||||
TRAILER_ENCAPSULATION,
|
||||
ARP_CACHE_TIMEOUT,
|
||||
IEEE802_3_ENCAPSULATION,
|
||||
DEFAULT_TCP_TTL,
|
||||
TCP_KEEPALIVE_INTERVAL,
|
||||
TCP_KEEPALIVE_GARBAGE,
|
||||
NIS_DOMAIN,
|
||||
NIS_SERVERS,
|
||||
NTP_SERVERS,
|
||||
VENDOR_ENCAPSULATED_OPTIONS,
|
||||
NETBIOS_NAME_SERVERS,
|
||||
NETBIOS_DD_SERVER,
|
||||
NETBIOS_NODE_TYPE,
|
||||
NETBIOS_SCOPE,
|
||||
FONT_SERVERS,
|
||||
X_DISPLAY_MANAGER,
|
||||
DHCP_REQUESTED_ADDRESS,
|
||||
DHCP_LEASE_TIME,
|
||||
DHCP_OPTION_OVERLOAD,
|
||||
DHCP_MESSAGE_TYPE,
|
||||
DHCP_SERVER_IDENTIFIER,
|
||||
DHCP_PARAMETER_REQUEST_LIST,
|
||||
DHCP_MESSAGE,
|
||||
DHCP_MAX_MESSAGE_SIZE,
|
||||
DHCP_RENEWAL_TIME,
|
||||
DHCP_REBINDING_TIME,
|
||||
VENDOR_CLASS_IDENTIFIER,
|
||||
DHCP_CLIENT_IDENTIFIER,
|
||||
NWIP_DOMAIN_NAME,
|
||||
NWIP_SUBOPTIONS,
|
||||
USER_CLASS = 77,
|
||||
FQDN = 81,
|
||||
DHCP_AGENT_OPTIONS = 82,
|
||||
SUBNET_SELECTION = 118,
|
||||
AUTHENTICATE = 210,
|
||||
END = 255
|
||||
};
|
||||
|
||||
/**
|
||||
* The DHCP option type.
|
||||
*/
|
||||
typedef PDUOption<uint8_t, DHCP> option;
|
||||
|
||||
/**
|
||||
* The type used to store the DHCP options.
|
||||
*/
|
||||
typedef std::vector<option> options_type;
|
||||
|
||||
/**
|
||||
* \brief Extracts metadata for this protocol based on the buffer provided
|
||||
*
|
||||
* \param buffer Pointer to a buffer
|
||||
* \param total_sz Size of the buffer pointed by buffer
|
||||
*/
|
||||
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Creates an instance of DHCP.
|
||||
*
|
||||
* This sets the hwtype and hlen fields to match the ethernet
|
||||
* type and length.
|
||||
*/
|
||||
DHCP();
|
||||
|
||||
/**
|
||||
* \brief Constructs a DHCP object from a buffer.
|
||||
*
|
||||
* If there is not enough size for a BootP header, or any of
|
||||
* the TLV options contains an invalid size field, then a
|
||||
* malformed_packet exception is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
DHCP(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Adds a new option to this DHCP PDU.
|
||||
* \param opt The option to be added.
|
||||
*/
|
||||
void add_option(const option& opt);
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
* \brief Adds a new option to this DHCP PDU.
|
||||
*
|
||||
* The option is move-constructed.
|
||||
*
|
||||
* \param opt The option to be added.
|
||||
*/
|
||||
void add_option(const option &opt);
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
* \brief Adds a new option to this DHCP PDU.
|
||||
*
|
||||
* The option is move-constructed.
|
||||
*
|
||||
* \param opt The option to be added.
|
||||
*/
|
||||
void add_option(option &&opt) {
|
||||
internal_add_option(opt);
|
||||
_options.push_back(std::move(opt));
|
||||
}
|
||||
#endif
|
||||
void add_option(option &&opt) {
|
||||
internal_add_option(opt);
|
||||
options_.push_back(std::move(opt));
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Removes a DHCP option.
|
||||
*
|
||||
* If there are multiple options of the given type, only the first one
|
||||
* will be removed.
|
||||
*
|
||||
* \param type The type of the option to be removed.
|
||||
* \return true if the option was removed, false otherwise.
|
||||
*/
|
||||
bool remove_option(OptionTypes type);
|
||||
|
||||
/**
|
||||
* \brief Searchs for an option that matchs the given flag.
|
||||
* \param opt_flag The flag to be searched.
|
||||
* \return A pointer to the option, or 0 if it was not found.
|
||||
*/
|
||||
const option* search_option(OptionTypes opt) const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for an option that matchs the given flag.
|
||||
* \param opt_flag The flag to be searched.
|
||||
* \return A pointer to the option, or 0 if it was not found.
|
||||
*/
|
||||
const option *search_option(OptionTypes opt) const;
|
||||
|
||||
/**
|
||||
* \brief Adds a type option to the option list.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param type The type of this DHCP PDU.
|
||||
*/
|
||||
void type(Flags type);
|
||||
|
||||
/**
|
||||
* \brief Adds an end option to the option list.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* The END option is not added automatically. You should explicitly
|
||||
* add it at the end of the DHCP options for the PDU to be
|
||||
* standard-compliant.
|
||||
*/
|
||||
void end();
|
||||
|
||||
/**
|
||||
* \brief Adds a server identifier option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param ip The server's IP address.
|
||||
*/
|
||||
void server_identifier(ipaddress_type ip);
|
||||
|
||||
/**
|
||||
* \brief Adds an IP address lease time option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param time The lease time.
|
||||
*/
|
||||
void lease_time(uint32_t time);
|
||||
|
||||
/**
|
||||
* \brief Adds a lease renewal time option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param time The lease renew time.
|
||||
*/
|
||||
void renewal_time(uint32_t time);
|
||||
|
||||
/**
|
||||
* \brief Adds a rebind time option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param time The lease rebind time.
|
||||
*/
|
||||
void rebind_time(uint32_t time);
|
||||
|
||||
/**
|
||||
* \brief Adds a subnet mask option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param mask The subnet mask.
|
||||
*/
|
||||
void subnet_mask(ipaddress_type mask);
|
||||
|
||||
/**
|
||||
* \brief Adds a routers option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param routers A list of ip addresses.
|
||||
*/
|
||||
void routers(const std::vector<ipaddress_type> &routers);
|
||||
|
||||
/**
|
||||
* \brief Adds a domain name servers option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param dns A list of ip addresses.
|
||||
*/
|
||||
void domain_name_servers(const std::vector<ipaddress_type> &dns);
|
||||
|
||||
/**
|
||||
* \brief Adds a broadcast address option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param addr The broadcast address.
|
||||
*/
|
||||
void broadcast(ipaddress_type addr);
|
||||
|
||||
/**
|
||||
* \brief Adds a requested address option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param addr The requested address.
|
||||
*/
|
||||
void requested_ip(ipaddress_type addr);
|
||||
|
||||
/**
|
||||
* \brief Adds a domain name option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param name The domain name.
|
||||
*/
|
||||
void domain_name(const std::string &name);
|
||||
/**
|
||||
* \brief Adds a type option to the option list.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param type The type of this DHCP PDU.
|
||||
*/
|
||||
void type(Flags type);
|
||||
|
||||
/**
|
||||
* \brief Adds an end option to the option list.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* The END option is not added automatically. You should explicitly
|
||||
* add it at the end of the DHCP options for the PDU to be
|
||||
* standard-compliant.
|
||||
*/
|
||||
void end();
|
||||
|
||||
/**
|
||||
* \brief Adds a server identifier option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param ip The server's IP address.
|
||||
*/
|
||||
void server_identifier(ipaddress_type ip);
|
||||
|
||||
/**
|
||||
* \brief Adds an IP address lease time option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param time The lease time.
|
||||
*/
|
||||
void lease_time(uint32_t time);
|
||||
|
||||
/**
|
||||
* \brief Adds a lease renewal time option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param time The lease renew time.
|
||||
*/
|
||||
void renewal_time(uint32_t time);
|
||||
|
||||
/**
|
||||
* \brief Adds a rebind time option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param time The lease rebind time.
|
||||
*/
|
||||
void rebind_time(uint32_t time);
|
||||
|
||||
/**
|
||||
* \brief Adds a subnet mask option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param mask The subnet mask.
|
||||
*/
|
||||
void subnet_mask(ipaddress_type mask);
|
||||
|
||||
/**
|
||||
* \brief Adds a routers option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param routers A list of ip addresses.
|
||||
*/
|
||||
void routers(const std::vector<ipaddress_type>& routers);
|
||||
|
||||
/**
|
||||
* \brief Adds a domain name servers option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param dns A list of ip addresses.
|
||||
*/
|
||||
void domain_name_servers(const std::vector<ipaddress_type>& dns);
|
||||
|
||||
/**
|
||||
* \brief Adds a broadcast address option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param addr The broadcast address.
|
||||
*/
|
||||
void broadcast(ipaddress_type addr);
|
||||
|
||||
/**
|
||||
* \brief Adds a requested address option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param addr The requested address.
|
||||
*/
|
||||
void requested_ip(ipaddress_type addr);
|
||||
|
||||
/**
|
||||
* \brief Adds a domain name option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param name The domain name.
|
||||
*/
|
||||
void domain_name(const std::string& name);
|
||||
|
||||
/**
|
||||
* \brief Adds a hostname option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param name The hostname.
|
||||
*/
|
||||
void hostname(const std::string &name);
|
||||
|
||||
// Option getters
|
||||
|
||||
/**
|
||||
* \brief Searchs for a type option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return uint8_t containing the type option.
|
||||
*/
|
||||
uint8_t type() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a server identifier option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return ipaddress_type Containing the server identifier.
|
||||
*/
|
||||
ipaddress_type server_identifier() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a lease time option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return uint32_t Containing the lease time.
|
||||
*/
|
||||
uint32_t lease_time() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a lease renewal time option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return uint32_t Containing the renewal time.
|
||||
*/
|
||||
uint32_t renewal_time() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a rebind time option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return uint32_t Containing the rebind time.
|
||||
*/
|
||||
uint32_t rebind_time() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a subnet mask option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return ipaddress_type Containing the subnet mask.
|
||||
*/
|
||||
ipaddress_type subnet_mask() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a routers option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return std::vector<ipaddress_type> Containing the routers
|
||||
* option data.
|
||||
*/
|
||||
std::vector<ipaddress_type> routers() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a dns option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return std::list<ipaddress_type> Contanining the DNS servers
|
||||
* provided.
|
||||
*/
|
||||
std::vector<ipaddress_type> domain_name_servers() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a broadcast option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return ipaddress_type Containing the broadcast address.
|
||||
*/
|
||||
ipaddress_type broadcast() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a requested option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return ipaddress_type Containing the requested IP address.
|
||||
*/
|
||||
ipaddress_type requested_ip() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a domain name option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return std::string Containing the domain name.
|
||||
*/
|
||||
std::string domain_name() const;
|
||||
/**
|
||||
* \brief Adds a hostname option.
|
||||
*
|
||||
* The new option is appended at the end of the list.
|
||||
*
|
||||
* \param name The hostname.
|
||||
*/
|
||||
void hostname(const std::string& name);
|
||||
|
||||
// Option getters
|
||||
|
||||
/**
|
||||
* \brief Searchs for a type option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return uint8_t containing the type option.
|
||||
*/
|
||||
uint8_t type() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a server identifier option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return ipaddress_type Containing the server identifier.
|
||||
*/
|
||||
ipaddress_type server_identifier() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a lease time option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return uint32_t Containing the lease time.
|
||||
*/
|
||||
uint32_t lease_time() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a lease renewal time option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return uint32_t Containing the renewal time.
|
||||
*/
|
||||
uint32_t renewal_time() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a rebind time option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return uint32_t Containing the rebind time.
|
||||
*/
|
||||
uint32_t rebind_time() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a subnet mask option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return ipaddress_type Containing the subnet mask.
|
||||
*/
|
||||
ipaddress_type subnet_mask() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a routers option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return std::vector<ipaddress_type> Containing the routers
|
||||
* option data.
|
||||
*/
|
||||
std::vector<ipaddress_type> routers() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a dns option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return The list of DNS servers provided.
|
||||
*/
|
||||
std::vector<ipaddress_type> domain_name_servers() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a broadcast option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return ipaddress_type Containing the broadcast address.
|
||||
*/
|
||||
ipaddress_type broadcast() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a requested option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return ipaddress_type Containing the requested IP address.
|
||||
*/
|
||||
ipaddress_type requested_ip() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a domain name option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return std::string Containing the domain name.
|
||||
*/
|
||||
std::string domain_name() const;
|
||||
|
||||
/**
|
||||
* \brief Searchs for a hostname option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return std::string Containing the hostname.
|
||||
*/
|
||||
std::string hostname() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the options list.
|
||||
* \return The option list.
|
||||
*/
|
||||
const options_type options() const { return _options; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the header size.
|
||||
* \return Returns the BOOTP header size.
|
||||
* \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
DHCP *clone() const {
|
||||
return new DHCP(*this);
|
||||
/**
|
||||
* \brief Searchs for a hostname option.
|
||||
*
|
||||
* If the option is not found, an option_not_found exception
|
||||
* is thrown.
|
||||
*
|
||||
* \return std::string Containing the hostname.
|
||||
*/
|
||||
std::string hostname() const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the options list.
|
||||
* \return The option list.
|
||||
*/
|
||||
const options_type options() const { return options_; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the header size.
|
||||
* \return Returns the BOOTP header size.
|
||||
* \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
DHCP* clone() const {
|
||||
return new DHCP(*this);
|
||||
}
|
||||
private:
|
||||
static const uint32_t MAX_DHCP_SIZE;
|
||||
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
template <typename T>
|
||||
T search_and_convert(OptionTypes opt) const {
|
||||
const option* option = search_option(opt);
|
||||
if (!option) {
|
||||
throw option_not_found();
|
||||
}
|
||||
private:
|
||||
static const uint32_t MAX_DHCP_SIZE;
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
return option->to<T>();
|
||||
}
|
||||
|
||||
void internal_add_option(const option& opt);
|
||||
serialization_type serialize_list(const std::vector<ipaddress_type>& ip_list);
|
||||
options_type::const_iterator search_option_iterator(OptionTypes opt) const;
|
||||
options_type::iterator search_option_iterator(OptionTypes opt);
|
||||
|
||||
options_type options_;
|
||||
uint32_t size_;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
T search_and_convert(OptionTypes opt) const {
|
||||
const option *option = search_option(opt);
|
||||
if(!option)
|
||||
throw option_not_found();
|
||||
return option->to<T>();
|
||||
}
|
||||
|
||||
void internal_add_option(const option &opt);
|
||||
serialization_type serialize_list(const std::vector<ipaddress_type> &ip_list);
|
||||
|
||||
options_type _options;
|
||||
uint32_t _size;
|
||||
};
|
||||
}
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_DHCP_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -31,19 +31,25 @@
|
||||
#define TINS_DHCPV6_H
|
||||
|
||||
#include <cstring>
|
||||
#include <list>
|
||||
#include "pdu.h"
|
||||
#include "endianness.h"
|
||||
#include "small_uint.h"
|
||||
#include "ipv6_address.h"
|
||||
#include "pdu_option.h"
|
||||
#include <tins/pdu.h>
|
||||
#include <tins/macros.h>
|
||||
#include <tins/endianness.h>
|
||||
#include <tins/small_uint.h>
|
||||
#include <tins/ipv6_address.h>
|
||||
#include <tins/pdu_option.h>
|
||||
|
||||
namespace Tins {
|
||||
namespace Memory {
|
||||
|
||||
class OutputMemoryStream;
|
||||
|
||||
} // Memory
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \class DHCPv6
|
||||
* \brief Represents a DHCPv6 PDU.
|
||||
*/
|
||||
class DHCPv6 : public PDU {
|
||||
class TINS_API DHCPv6 : public PDU {
|
||||
public:
|
||||
/**
|
||||
* Represents a DHCPv6 option.
|
||||
@@ -156,7 +162,7 @@ public:
|
||||
/**
|
||||
* The type used to store the DHCPv6 options.
|
||||
*/
|
||||
typedef std::list<option> options_type;
|
||||
typedef std::vector<option> options_type;
|
||||
|
||||
/**
|
||||
* The type used to store IP addresses.
|
||||
@@ -182,7 +188,7 @@ public:
|
||||
const options_type& options = options_type())
|
||||
: id(id), t1(t1), t2(t2), options(options) {}
|
||||
|
||||
static ia_na_type from_option(const option &opt);
|
||||
static ia_na_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -199,7 +205,7 @@ public:
|
||||
const options_type& options = options_type())
|
||||
: id(id), options(options) {}
|
||||
|
||||
static ia_ta_type from_option(const option &opt);
|
||||
static ia_ta_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -218,7 +224,7 @@ public:
|
||||
: address(address), preferred_lifetime(preferred_lifetime),
|
||||
valid_lifetime(valid_lifetime), options(options) {}
|
||||
|
||||
static ia_address_type from_option(const option &opt);
|
||||
static ia_address_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -233,11 +239,11 @@ public:
|
||||
|
||||
authentication_type(uint8_t protocol = 0, uint8_t algorithm = 0,
|
||||
uint8_t rdm = 0, uint64_t replay_detection = 0,
|
||||
const auth_info_type &auth_info = auth_info_type())
|
||||
const auth_info_type& auth_info = auth_info_type())
|
||||
: protocol(protocol), algorithm(algorithm), rdm(rdm),
|
||||
replay_detection(replay_detection), auth_info(auth_info) {}
|
||||
|
||||
static authentication_type from_option(const option &opt);
|
||||
static authentication_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -247,10 +253,10 @@ public:
|
||||
uint16_t code;
|
||||
std::string message;
|
||||
|
||||
status_code_type(uint16_t code = 0, const std::string &message = "")
|
||||
status_code_type(uint16_t code = 0, const std::string& message = "")
|
||||
: code(code), message(message) { }
|
||||
|
||||
static status_code_type from_option(const option &opt);
|
||||
static status_code_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -263,10 +269,10 @@ public:
|
||||
data_type data;
|
||||
|
||||
vendor_info_type(uint32_t enterprise_number = 0,
|
||||
const data_type &data = data_type())
|
||||
const data_type& data = data_type())
|
||||
: enterprise_number(enterprise_number), data(data) { }
|
||||
|
||||
static vendor_info_type from_option(const option &opt);
|
||||
static vendor_info_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
|
||||
@@ -283,13 +289,10 @@ public:
|
||||
typedef std::vector<class_option_data_type> data_type;
|
||||
data_type data;
|
||||
|
||||
user_class_type(const data_type &data = data_type())
|
||||
: data(data)
|
||||
{
|
||||
user_class_type(const data_type& data = data_type())
|
||||
: data(data) { }
|
||||
|
||||
}
|
||||
|
||||
static user_class_type from_option(const option &opt);
|
||||
static user_class_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -302,11 +305,11 @@ public:
|
||||
class_data_type vendor_class_data;
|
||||
|
||||
vendor_class_type(uint32_t enterprise_number = 0,
|
||||
const class_data_type &vendor_class_data = class_data_type())
|
||||
const class_data_type& vendor_class_data = class_data_type())
|
||||
: enterprise_number(enterprise_number),
|
||||
vendor_class_data(vendor_class_data) { }
|
||||
|
||||
static vendor_class_type from_option(const option &opt);
|
||||
static vendor_class_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -322,12 +325,12 @@ public:
|
||||
lladdress_type lladdress;
|
||||
|
||||
duid_llt(uint16_t hw_type = 0, uint32_t time = 0,
|
||||
const lladdress_type &lladdress = lladdress_type())
|
||||
const lladdress_type& lladdress = lladdress_type())
|
||||
: hw_type(hw_type), time(time), lladdress(lladdress) {}
|
||||
|
||||
PDU::serialization_type serialize() const;
|
||||
|
||||
static duid_llt from_bytes(const uint8_t *buffer, uint32_t total_sz);
|
||||
static duid_llt from_bytes(const uint8_t* buffer, uint32_t total_sz);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -341,12 +344,12 @@ public:
|
||||
identifier_type identifier;
|
||||
|
||||
duid_en(uint32_t enterprise_number = 0,
|
||||
const identifier_type &identifier = identifier_type())
|
||||
const identifier_type& identifier = identifier_type())
|
||||
: enterprise_number(enterprise_number), identifier(identifier) {}
|
||||
|
||||
PDU::serialization_type serialize() const;
|
||||
|
||||
static duid_en from_bytes(const uint8_t *buffer, uint32_t total_sz);
|
||||
static duid_en from_bytes(const uint8_t* buffer, uint32_t total_sz);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -360,12 +363,12 @@ public:
|
||||
lladdress_type lladdress;
|
||||
|
||||
duid_ll(uint16_t hw_type = 0,
|
||||
const lladdress_type &lladdress = lladdress_type())
|
||||
const lladdress_type& lladdress = lladdress_type())
|
||||
: hw_type(hw_type), lladdress(lladdress) {}
|
||||
|
||||
PDU::serialization_type serialize() const;
|
||||
|
||||
static duid_ll from_bytes(const uint8_t *buffer, uint32_t total_sz);
|
||||
static duid_ll from_bytes(const uint8_t* buffer, uint32_t total_sz);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -378,19 +381,19 @@ public:
|
||||
uint16_t id;
|
||||
data_type data;
|
||||
|
||||
duid_type(uint16_t id = 0, const data_type &data = data_type())
|
||||
duid_type(uint16_t id = 0, const data_type& data = data_type())
|
||||
: id(id), data(data) {}
|
||||
|
||||
duid_type(const duid_llt &identifier)
|
||||
duid_type(const duid_llt& identifier)
|
||||
: id(duid_llt::duid_id), data(identifier.serialize()) {}
|
||||
|
||||
duid_type(const duid_en &identifier)
|
||||
duid_type(const duid_en& identifier)
|
||||
: id(duid_en::duid_id), data(identifier.serialize()) {}
|
||||
|
||||
duid_type(const duid_ll &identifier)
|
||||
: id(duid_en::duid_id), data(identifier.serialize()) {}
|
||||
duid_type(const duid_ll& identifier)
|
||||
: id(duid_ll::duid_id), data(identifier.serialize()) {}
|
||||
|
||||
static duid_type from_option(const option &opt);
|
||||
static duid_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -408,6 +411,14 @@ public:
|
||||
*/
|
||||
typedef std::vector<uint8_t> interface_id_type;
|
||||
|
||||
/**
|
||||
* \brief Extracts metadata for this protocol based on the buffer provided
|
||||
*
|
||||
* \param buffer Pointer to a buffer
|
||||
* \param total_sz Size of the buffer pointed by buffer
|
||||
*/
|
||||
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
@@ -423,7 +434,7 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
DHCPv6(const uint8_t *buffer, uint32_t total_sz);
|
||||
DHCPv6(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
// Getters
|
||||
|
||||
@@ -433,7 +444,7 @@ public:
|
||||
* \return The stored message type field.
|
||||
*/
|
||||
MessageType msg_type() const {
|
||||
return static_cast<MessageType>(header_data[0]);
|
||||
return static_cast<MessageType>(header_data_[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -441,7 +452,9 @@ public:
|
||||
*
|
||||
* \return The stored hop count field.
|
||||
*/
|
||||
uint8_t hop_count() const { return header_data[1]; }
|
||||
uint8_t hop_count() const {
|
||||
return header_data_[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the transaction id field.
|
||||
@@ -449,7 +462,7 @@ public:
|
||||
* \return The stored transaction id field.
|
||||
*/
|
||||
small_uint<24> transaction_id() const {
|
||||
return (header_data[1] << 16) | (header_data[2] << 8) | header_data[3];
|
||||
return (header_data_[1] << 16) | (header_data_[2] << 8) | header_data_[3];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -457,21 +470,27 @@ public:
|
||||
*
|
||||
* \return The stored peer address field.
|
||||
*/
|
||||
const ipaddress_type &peer_address() const { return peer_addr; }
|
||||
const ipaddress_type& peer_address() const {
|
||||
return peer_addr_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the link address field.
|
||||
*
|
||||
* \return The stored link address field.
|
||||
*/
|
||||
const ipaddress_type &link_address() const { return link_addr; }
|
||||
const ipaddress_type& link_address() const {
|
||||
return link_addr_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the DHCPv6 options.
|
||||
*
|
||||
* \return The stored options.
|
||||
*/
|
||||
const options_type &options() const { return options_; }
|
||||
const options_type& options() const {
|
||||
return options_;
|
||||
}
|
||||
|
||||
// Setters
|
||||
/**
|
||||
@@ -500,14 +519,14 @@ public:
|
||||
*
|
||||
* \param count The new peer address.
|
||||
*/
|
||||
void peer_address(const ipaddress_type &addr);
|
||||
void peer_address(const ipaddress_type& addr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the link address field.
|
||||
*
|
||||
* \param count The new link address.
|
||||
*/
|
||||
void link_address(const ipaddress_type &addr);
|
||||
void link_address(const ipaddress_type& addr);
|
||||
|
||||
// Option getters
|
||||
|
||||
@@ -673,7 +692,7 @@ public:
|
||||
*
|
||||
* \param value The new IA_NA option data.
|
||||
*/
|
||||
void ia_na(const ia_na_type &value);
|
||||
void ia_na(const ia_na_type& value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Identity Association for Temporary
|
||||
@@ -681,21 +700,21 @@ public:
|
||||
*
|
||||
* \param value The new IA_TA option data.
|
||||
*/
|
||||
void ia_ta(const ia_ta_type &value);
|
||||
void ia_ta(const ia_ta_type& value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Identity Association Address option.
|
||||
*
|
||||
* \param value The new IA Address option data.
|
||||
*/
|
||||
void ia_address(const ia_address_type &value);
|
||||
void ia_address(const ia_address_type& value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Identity Association Address option.
|
||||
*
|
||||
* \param value The new Option Request option data.
|
||||
*/
|
||||
void option_request(const option_request_type &value);
|
||||
void option_request(const option_request_type& value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Preference option.
|
||||
@@ -716,28 +735,28 @@ public:
|
||||
*
|
||||
* \param value The new Relay Message option data.
|
||||
*/
|
||||
void relay_message(const relay_msg_type &value);
|
||||
void relay_message(const relay_msg_type& value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Authentication option.
|
||||
*
|
||||
* \param value The new Authentication option data.
|
||||
*/
|
||||
void authentication(const authentication_type &value);
|
||||
void authentication(const authentication_type& value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Server Unicast option.
|
||||
*
|
||||
* \param value The new Server Unicast option data.
|
||||
*/
|
||||
void server_unicast(const ipaddress_type &value);
|
||||
void server_unicast(const ipaddress_type& value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Status Code option.
|
||||
*
|
||||
* \param value The new Status Code option data.
|
||||
*/
|
||||
void status_code(const status_code_type &value);
|
||||
void status_code(const status_code_type& value);
|
||||
|
||||
/**
|
||||
* \brief Adds a Rapid Commit option.
|
||||
@@ -749,28 +768,28 @@ public:
|
||||
*
|
||||
* \param value The new User Class option data.
|
||||
*/
|
||||
void user_class(const user_class_type &value);
|
||||
void user_class(const user_class_type& value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Vendor Class option.
|
||||
*
|
||||
* \param value The new Vendor Class option data.
|
||||
*/
|
||||
void vendor_class(const vendor_class_type &value);
|
||||
void vendor_class(const vendor_class_type& value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Vendor-specific Information option.
|
||||
*
|
||||
* \param value The new Vendor-specific Information option data.
|
||||
*/
|
||||
void vendor_info(const vendor_info_type &value);
|
||||
void vendor_info(const vendor_info_type& value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Interface ID option.
|
||||
*
|
||||
* \param value The new Interface ID option data.
|
||||
*/
|
||||
void interface_id(const interface_id_type &value);
|
||||
void interface_id(const interface_id_type& value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Reconfigure Message option.
|
||||
@@ -789,14 +808,14 @@ public:
|
||||
*
|
||||
* \param value The new Client Identifier option data.
|
||||
*/
|
||||
void client_id(const duid_type &value);
|
||||
void client_id(const duid_type& value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the Server Identifier option.
|
||||
*
|
||||
* \param value The new Server Identifier option data.
|
||||
*/
|
||||
void server_id(const duid_type &value);
|
||||
void server_id(const duid_type& value);
|
||||
|
||||
// Other stuff
|
||||
|
||||
@@ -813,117 +832,92 @@ public:
|
||||
*
|
||||
* \param opt The option to be added
|
||||
*/
|
||||
void add_option(const option &opt);
|
||||
void add_option(const option& opt);
|
||||
|
||||
/**
|
||||
* \brief Searchs for an option that matchs the given flag.
|
||||
* \brief Removes a DHCPv6 option.
|
||||
*
|
||||
* If there are multiple options of the given type, only the first one
|
||||
* will be removed.
|
||||
*
|
||||
* \param type The type of the option to be removed.
|
||||
* \return true if the option was removed, false otherwise.
|
||||
*/
|
||||
bool remove_option(OptionTypes type);
|
||||
|
||||
/**
|
||||
* \brief Searchs for an option that matchs the given type.
|
||||
*
|
||||
* If the option is not found, a null pointer is returned.
|
||||
* Deleting the returned pointer will result in <b>undefined
|
||||
* behaviour</b>.
|
||||
*
|
||||
* \param id The option identifier to be searched.
|
||||
* \param type The option identifier to be searched.
|
||||
*/
|
||||
const option *search_option(OptionTypes id) const;
|
||||
const option* search_option(OptionTypes type) const;
|
||||
|
||||
// PDU stuff
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
* This metod overrides PDU::header_size. \sa PDU::header_size
|
||||
* This method overrides PDU::header_size. \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Check wether ptr points to a valid response for this PDU.
|
||||
* \brief Check whether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
|
||||
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
DHCPv6 *clone() const {
|
||||
DHCPv6* clone() const {
|
||||
return new DHCPv6(*this);
|
||||
}
|
||||
private:
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *);
|
||||
uint8_t* write_option(const option &option, uint8_t* buffer) const;
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz);
|
||||
void write_option(const option& option, Memory::OutputMemoryStream& stream) const;
|
||||
options_type::const_iterator search_option_iterator(OptionTypes type) const;
|
||||
options_type::iterator search_option_iterator(OptionTypes type);
|
||||
|
||||
template<template <typename> class Functor>
|
||||
const option *safe_search_option(OptionTypes opt, uint32_t size) const {
|
||||
const option *option = search_option(opt);
|
||||
if(!option || Functor<uint32_t>()(option->data_size(), size))
|
||||
template <template <typename> class Functor>
|
||||
const option* safe_search_option(OptionTypes opt, uint32_t size) const {
|
||||
const option* option = search_option(opt);
|
||||
if (!option || Functor<uint32_t>()(option->data_size(), size)) {
|
||||
throw option_not_found();
|
||||
}
|
||||
return option;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T search_and_convert(OptionTypes opt) const {
|
||||
const option *option = search_option(opt);
|
||||
if(!option)
|
||||
const option* option = search_option(opt);
|
||||
if (!option) {
|
||||
throw option_not_found();
|
||||
}
|
||||
return option->to<T>();
|
||||
}
|
||||
|
||||
uint8_t header_data[4];
|
||||
uint32_t options_size;
|
||||
ipaddress_type link_addr, peer_addr;
|
||||
uint8_t header_data_[4];
|
||||
uint32_t options_size_;
|
||||
ipaddress_type link_addr_, peer_addr_;
|
||||
options_type options_;
|
||||
};
|
||||
};
|
||||
|
||||
namespace Internals {
|
||||
template<typename InputIterator>
|
||||
void class_option_data2option(InputIterator start, InputIterator end,
|
||||
std::vector<uint8_t>& buffer, size_t start_index = 0)
|
||||
{
|
||||
size_t index = start_index;
|
||||
uint16_t uint16_t_buffer;
|
||||
while(start != end) {
|
||||
buffer.resize(buffer.size() + sizeof(uint16_t) + start->size());
|
||||
uint16_t_buffer = Endian::host_to_be<uint16_t>(start->size());
|
||||
std::memcpy(&buffer[index], &uint16_t_buffer, sizeof(uint16_t));
|
||||
index += sizeof(uint16_t);
|
||||
std::copy(start->begin(), start->end(), buffer.begin() + index);
|
||||
index += start->size();
|
||||
|
||||
start++;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename OutputType>
|
||||
OutputType option2class_option_data(const uint8_t *ptr, uint32_t total_sz)
|
||||
{
|
||||
typedef typename OutputType::value_type value_type;
|
||||
OutputType output;
|
||||
size_t index = 0;
|
||||
while(index + 2 < total_sz) {
|
||||
uint16_t size;
|
||||
std::memcpy(&size, ptr + index, sizeof(uint16_t));
|
||||
size = Endian::be_to_host(size);
|
||||
index += sizeof(uint16_t);
|
||||
if(index + size > total_sz)
|
||||
throw option_not_found();
|
||||
output.push_back(
|
||||
value_type(ptr + index, ptr + index + size)
|
||||
);
|
||||
index += size;
|
||||
}
|
||||
if(index != total_sz)
|
||||
throw malformed_option();
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_DHCPV6_H
|
||||
|
||||
1621
include/tins/dns.h
1621
include/tins/dns.h
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -27,18 +27,18 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <tins/config.h>
|
||||
|
||||
#if !defined(TINS_DOT_11) && defined(HAVE_DOT11)
|
||||
#if !defined(TINS_DOT_11) && defined(TINS_HAVE_DOT11)
|
||||
#define TINS_DOT_11
|
||||
|
||||
#include "dot11/dot11_base.h"
|
||||
#include "dot11/dot11_data.h"
|
||||
#include "dot11/dot11_mgmt.h"
|
||||
#include "dot11/dot11_beacon.h"
|
||||
#include "dot11/dot11_assoc.h"
|
||||
#include "dot11/dot11_auth.h"
|
||||
#include "dot11/dot11_probe.h"
|
||||
#include "dot11/dot11_control.h"
|
||||
#include <tins/dot11/dot11_base.h>
|
||||
#include <tins/dot11/dot11_data.h>
|
||||
#include <tins/dot11/dot11_mgmt.h>
|
||||
#include <tins/dot11/dot11_beacon.h>
|
||||
#include <tins/dot11/dot11_assoc.h>
|
||||
#include <tins/dot11/dot11_auth.h>
|
||||
#include <tins/dot11/dot11_probe.h>
|
||||
#include <tins/dot11/dot11_control.h>
|
||||
|
||||
#endif // TINS_DOT_11
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
FILE(GLOB INCLUDE_FILES "*.h")
|
||||
INSTALL(
|
||||
FILES ${INCLUDE_FILES}
|
||||
DESTINATION include/tins/dot11
|
||||
COMPONENT Headers
|
||||
)
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -27,19 +27,20 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../config.h"
|
||||
#include <tins/config.h>
|
||||
|
||||
#if !defined(TINS_DOT11_DOT11_ASSOC_H) && defined(HAVE_DOT11)
|
||||
#if !defined(TINS_DOT11_DOT11_ASSOC_H) && defined(TINS_HAVE_DOT11)
|
||||
#define TINS_DOT11_DOT11_ASSOC_H
|
||||
|
||||
#include "../dot11/dot11_mgmt.h"
|
||||
#include <tins/dot11/dot11_mgmt.h>
|
||||
#include <tins/macros.h>
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \brief Class representing a Disassociation frame in the IEEE 802.11 Protocol.
|
||||
*
|
||||
*/
|
||||
class Dot11Disassoc : public Dot11ManagementFrame {
|
||||
class TINS_API Dot11Disassoc : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -55,8 +56,8 @@ public:
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11Disassoc(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
Dot11Disassoc(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11Disassoc object from a buffer and
|
||||
@@ -72,14 +73,16 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11Disassoc(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11Disassoc(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the reason code field.
|
||||
*
|
||||
* \return The stored reason code.
|
||||
*/
|
||||
uint16_t reason_code() const { return Endian::le_to_host(_body.reason_code); }
|
||||
uint16_t reason_code() const {
|
||||
return Endian::le_to_host(body_.reason_code);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the reason code field.
|
||||
@@ -100,10 +103,12 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -116,24 +121,24 @@ public:
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11Disassoc *clone() const {
|
||||
Dot11Disassoc* clone() const {
|
||||
return new Dot11Disassoc(*this);
|
||||
}
|
||||
private:
|
||||
struct DisassocBody {
|
||||
struct dot11_disassoc_body {
|
||||
uint16_t reason_code;
|
||||
};
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
|
||||
|
||||
DisassocBody _body;
|
||||
dot11_disassoc_body body_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Class representing an Association Request frame in the IEEE 802.11 Protocol.
|
||||
*
|
||||
*/
|
||||
class Dot11AssocRequest : public Dot11ManagementFrame {
|
||||
class TINS_API Dot11AssocRequest : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -149,8 +154,8 @@ public:
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11AssocRequest(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
Dot11AssocRequest(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11AssocRequest object from a buffer
|
||||
@@ -166,7 +171,7 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11AssocRequest(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11AssocRequest(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
@@ -174,7 +179,9 @@ public:
|
||||
* \return A constant refereence to the stored Capabilities
|
||||
* Information field.
|
||||
*/
|
||||
const capability_information& capabilities() const { return _body.capability;}
|
||||
const capability_information& capabilities() const {
|
||||
return body_.capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
@@ -182,14 +189,18 @@ public:
|
||||
* \return A refereence to the stored Capabilities Information
|
||||
* field.
|
||||
*/
|
||||
capability_information& capabilities() { return _body.capability;}
|
||||
capability_information& capabilities() {
|
||||
return body_.capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the listen interval field.
|
||||
*
|
||||
* \return The stored listen interval field.
|
||||
*/
|
||||
uint16_t listen_interval() const { return Endian::le_to_host(_body.listen_interval); }
|
||||
uint16_t listen_interval() const {
|
||||
return Endian::le_to_host(body_.listen_interval);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the listen interval field.
|
||||
@@ -210,10 +221,12 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -226,25 +239,25 @@ public:
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11AssocRequest *clone() const {
|
||||
Dot11AssocRequest* clone() const {
|
||||
return new Dot11AssocRequest(*this);
|
||||
}
|
||||
private:
|
||||
struct AssocReqBody {
|
||||
struct dot11_assoc_request_body {
|
||||
capability_information capability;
|
||||
uint16_t listen_interval;
|
||||
};
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
|
||||
|
||||
AssocReqBody _body;
|
||||
dot11_assoc_request_body body_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Class representing an Association Response frame in the IEEE 802.11 Protocol.
|
||||
*
|
||||
*/
|
||||
class Dot11AssocResponse : public Dot11ManagementFrame {
|
||||
class TINS_API Dot11AssocResponse : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -260,8 +273,8 @@ public:
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11AssocResponse(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
Dot11AssocResponse(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructor which creates a Dot11AssocResponse object
|
||||
@@ -277,7 +290,7 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11AssocResponse(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11AssocResponse(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information field.
|
||||
@@ -285,7 +298,9 @@ public:
|
||||
* \return A constant reference to the stored Capabilities
|
||||
* Information field.
|
||||
*/
|
||||
const capability_information& capabilities() const { return _body.capability;}
|
||||
const capability_information& capabilities() const {
|
||||
return body_.capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information field.
|
||||
@@ -293,21 +308,27 @@ public:
|
||||
* \return A reference to the stored Capabilities
|
||||
* Information field.
|
||||
*/
|
||||
capability_information& capabilities() { return _body.capability;}
|
||||
capability_information& capabilities() {
|
||||
return body_.capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the status code field.
|
||||
*
|
||||
* \return The stored status code.
|
||||
*/
|
||||
uint16_t status_code() const { return Endian::le_to_host(_body.status_code); }
|
||||
uint16_t status_code() const {
|
||||
return Endian::le_to_host(body_.status_code);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the AID field.
|
||||
*
|
||||
* \return The stored AID field.
|
||||
*/
|
||||
uint16_t aid() const { return Endian::le_to_host(_body.aid); }
|
||||
uint16_t aid() const {
|
||||
return Endian::le_to_host(body_.aid);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the status code.
|
||||
@@ -335,10 +356,12 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -351,26 +374,26 @@ public:
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11AssocResponse *clone() const {
|
||||
Dot11AssocResponse* clone() const {
|
||||
return new Dot11AssocResponse(*this);
|
||||
}
|
||||
private:
|
||||
struct AssocRespBody {
|
||||
struct dot11_assoc_response_body {
|
||||
capability_information capability;
|
||||
uint16_t status_code;
|
||||
uint16_t aid;
|
||||
};
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
|
||||
|
||||
AssocRespBody _body;
|
||||
dot11_assoc_response_body body_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Class representing an ReAssociation Request frame in the IEEE 802.11 Protocol.
|
||||
*
|
||||
*/
|
||||
class Dot11ReAssocRequest : public Dot11ManagementFrame {
|
||||
class TINS_API Dot11ReAssocRequest : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -386,8 +409,8 @@ public:
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11ReAssocRequest(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
Dot11ReAssocRequest(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11AssocRequest object from a buffer
|
||||
@@ -403,7 +426,7 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11ReAssocRequest(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11ReAssocRequest(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
@@ -411,7 +434,9 @@ public:
|
||||
* \return A constant reference to the stored Capabilities
|
||||
* Information field.
|
||||
*/
|
||||
const capability_information& capabilities() const { return _body.capability;}
|
||||
const capability_information& capabilities() const {
|
||||
return body_.capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
@@ -419,21 +444,27 @@ public:
|
||||
* \return A reference to the stored Capabilities Information
|
||||
* field.
|
||||
*/
|
||||
capability_information& capabilities() { return _body.capability;}
|
||||
capability_information& capabilities() {
|
||||
return body_.capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the listen interval field.
|
||||
*
|
||||
* \return The stored listen interval.
|
||||
*/
|
||||
uint16_t listen_interval() const { return Endian::le_to_host(_body.listen_interval); }
|
||||
uint16_t listen_interval() const {
|
||||
return Endian::le_to_host(body_.listen_interval);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the current ap field.
|
||||
*
|
||||
* \return The current ap.
|
||||
*/
|
||||
address_type current_ap() const { return _body.current_ap; }
|
||||
address_type current_ap() const {
|
||||
return body_.current_ap;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the listen interval field.
|
||||
@@ -447,7 +478,7 @@ public:
|
||||
*
|
||||
* \param new_current_ap The address of the current ap.
|
||||
*/
|
||||
void current_ap(const address_type &new_current_ap);
|
||||
void current_ap(const address_type& new_current_ap);
|
||||
|
||||
/**
|
||||
* \brief Returns the frame's header length.
|
||||
@@ -461,10 +492,12 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -477,26 +510,26 @@ public:
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11ReAssocRequest *clone() const {
|
||||
Dot11ReAssocRequest* clone() const {
|
||||
return new Dot11ReAssocRequest(*this);
|
||||
}
|
||||
private:
|
||||
struct ReAssocReqBody {
|
||||
struct dot11_reassoc_request_body {
|
||||
capability_information capability;
|
||||
uint16_t listen_interval;
|
||||
uint8_t current_ap[address_type::address_size];
|
||||
};
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
|
||||
|
||||
ReAssocReqBody _body;
|
||||
dot11_reassoc_request_body body_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief IEEE 802.11 ReAssociation Response frame.
|
||||
*
|
||||
*/
|
||||
class Dot11ReAssocResponse : public Dot11ManagementFrame {
|
||||
class TINS_API Dot11ReAssocResponse : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -512,8 +545,8 @@ public:
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11ReAssocResponse(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
Dot11ReAssocResponse(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11ReAssocResponse object from a buffer
|
||||
@@ -529,7 +562,7 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11ReAssocResponse(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11ReAssocResponse(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
@@ -537,7 +570,9 @@ public:
|
||||
* \return A constant reference to the stored Capabilities
|
||||
* Information field.
|
||||
*/
|
||||
const capability_information& capabilities() const { return _body.capability;}
|
||||
const capability_information& capabilities() const {
|
||||
return body_.capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
@@ -545,21 +580,27 @@ public:
|
||||
* \return A reference to the stored Capabilities Information
|
||||
* field.
|
||||
*/
|
||||
capability_information& capabilities() { return _body.capability;}
|
||||
capability_information& capabilities() {
|
||||
return body_.capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the status code field.
|
||||
*
|
||||
* \return The stored status code.
|
||||
*/
|
||||
uint16_t status_code() const { return Endian::le_to_host(_body.status_code); }
|
||||
uint16_t status_code() const {
|
||||
return Endian::le_to_host(body_.status_code);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the AID field.
|
||||
*
|
||||
* \return The stored AID field value.
|
||||
*/
|
||||
uint16_t aid() const { return Endian::le_to_host(_body.aid); }
|
||||
uint16_t aid() const {
|
||||
return Endian::le_to_host(body_.aid);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the status code field.
|
||||
@@ -587,10 +628,12 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -603,20 +646,21 @@ public:
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11ReAssocResponse *clone() const {
|
||||
Dot11ReAssocResponse* clone() const {
|
||||
return new Dot11ReAssocResponse(*this);
|
||||
}
|
||||
private:
|
||||
struct ReAssocRespBody {
|
||||
struct dot11_reassoc_response_body {
|
||||
capability_information capability;
|
||||
uint16_t status_code;
|
||||
uint16_t aid;
|
||||
};
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
|
||||
|
||||
ReAssocRespBody _body;
|
||||
dot11_reassoc_response_body body_;
|
||||
};
|
||||
|
||||
} // namespace Tins
|
||||
|
||||
#endif // TINS_DOT11_DOT11_ASSOC_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -27,18 +27,19 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../config.h"
|
||||
#include <tins/config.h>
|
||||
|
||||
#if !defined(TINS_DOT11_DOT11_AUTH_H) && defined(HAVE_DOT11)
|
||||
#if !defined(TINS_DOT11_DOT11_AUTH_H) && defined(TINS_HAVE_DOT11)
|
||||
#define TINS_DOT11_DOT11_AUTH_H
|
||||
|
||||
#include "../dot11/dot11_mgmt.h"
|
||||
#include <tins/dot11/dot11_mgmt.h>
|
||||
#include <tins/macros.h>
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \brief IEEE 802.11 Authentication Request frame.
|
||||
*/
|
||||
class Dot11Authentication : public Dot11ManagementFrame {
|
||||
class TINS_API Dot11Authentication : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -54,8 +55,8 @@ public:
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11Authentication(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
Dot11Authentication(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11Authentication object from a buffer
|
||||
@@ -71,28 +72,33 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11Authentication(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11Authentication(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the Authetication Algorithm Number field.
|
||||
*
|
||||
* \return The stored authentication algorithm number.
|
||||
*/
|
||||
uint16_t auth_algorithm() const {return Endian::le_to_host(_body.auth_algorithm); }
|
||||
uint16_t auth_algorithm() const {
|
||||
return Endian::le_to_host(body_.auth_algorithm); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the Authetication Sequence Number field.
|
||||
*
|
||||
* \return The stored authentication sequence number.
|
||||
*/
|
||||
uint16_t auth_seq_number() const {return Endian::le_to_host(_body.auth_seq_number); }
|
||||
uint16_t auth_seq_number() const {
|
||||
return Endian::le_to_host(body_.auth_seq_number);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the status code field.
|
||||
*
|
||||
* \return The stored status code.
|
||||
*/
|
||||
uint16_t status_code() const { return Endian::le_to_host(_body.status_code); }
|
||||
uint16_t status_code() const {
|
||||
return Endian::le_to_host(body_.status_code);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the Authetication Algorithm Number field.
|
||||
@@ -129,10 +135,12 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -145,27 +153,26 @@ public:
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11Authentication *clone() const {
|
||||
Dot11Authentication* clone() const {
|
||||
return new Dot11Authentication(*this);
|
||||
}
|
||||
private:
|
||||
struct AuthBody {
|
||||
struct dot11_auth_body {
|
||||
uint16_t auth_algorithm;
|
||||
uint16_t auth_seq_number;
|
||||
uint16_t status_code;
|
||||
};
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
AuthBody _body;
|
||||
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
|
||||
|
||||
dot11_auth_body body_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief IEEE 802.11 Deauthentication frame.
|
||||
*
|
||||
*/
|
||||
class Dot11Deauthentication : public Dot11ManagementFrame {
|
||||
class TINS_API Dot11Deauthentication : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -181,8 +188,8 @@ public:
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11Deauthentication(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
Dot11Deauthentication(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11Deauthentication object from a buffer
|
||||
@@ -198,14 +205,16 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11Deauthentication(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11Deauthentication(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the reason code field.
|
||||
*
|
||||
* \return The reason code to be set.
|
||||
*/
|
||||
uint16_t reason_code() const { return Endian::le_to_host(_body.reason_code); }
|
||||
uint16_t reason_code() const {
|
||||
return Endian::le_to_host(body_.reason_code);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the reason code field.
|
||||
@@ -226,10 +235,12 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -242,19 +253,19 @@ public:
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11Deauthentication *clone() const {
|
||||
Dot11Deauthentication* clone() const {
|
||||
return new Dot11Deauthentication(*this);
|
||||
}
|
||||
private:
|
||||
struct DeauthBody {
|
||||
struct dot11_deauth_body {
|
||||
uint16_t reason_code;
|
||||
};
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
|
||||
|
||||
DeauthBody _body;
|
||||
dot11_deauth_body body_;
|
||||
};
|
||||
|
||||
} // namespace Tins
|
||||
|
||||
|
||||
#endif // TINS_DOT11_DOT11_AUTH_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -27,27 +27,31 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../config.h"
|
||||
#include <tins/config.h>
|
||||
|
||||
#if !defined(TINS_DOT11_DOT11_H) && defined(HAVE_DOT11)
|
||||
#if !defined(TINS_DOT11_DOT11_H) && defined(TINS_HAVE_DOT11)
|
||||
#define TINS_DOT11_DOT11_H
|
||||
|
||||
#include <list>
|
||||
#include "../pdu.h"
|
||||
#include "../pdu_option.h"
|
||||
#include "../small_uint.h"
|
||||
#include "../hw_address.h"
|
||||
#include "../endianness.h"
|
||||
#include "../cxxstd.h"
|
||||
#include "../macros.h"
|
||||
#include <tins/pdu.h>
|
||||
#include <tins/pdu_option.h>
|
||||
#include <tins/small_uint.h>
|
||||
#include <tins/hw_address.h>
|
||||
#include <tins/endianness.h>
|
||||
#include <tins/cxxstd.h>
|
||||
#include <tins/macros.h>
|
||||
|
||||
namespace Tins {
|
||||
namespace Memory {
|
||||
class InputMemoryStream;
|
||||
class OutputMemoryStream;
|
||||
} // Memory
|
||||
|
||||
class RSNInformation;
|
||||
|
||||
/**
|
||||
* \brief Class representing an 802.11 frame.
|
||||
*/
|
||||
class Dot11 : public PDU {
|
||||
class TINS_API Dot11 : public PDU {
|
||||
public:
|
||||
/**
|
||||
* The type used to store hardware addresses.
|
||||
@@ -62,7 +66,7 @@ public:
|
||||
/**
|
||||
* The type used to store tagged options.
|
||||
*/
|
||||
typedef std::list<option> options_type;
|
||||
typedef std::vector<option> options_type;
|
||||
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -123,9 +127,148 @@ public:
|
||||
ERP_INFORMATION,
|
||||
TS_DELAY,
|
||||
TCLAS_PROCESSING,
|
||||
QOS_CAPABILITY = 46,
|
||||
HT_CAPABILITY,
|
||||
QOS_CAPABILITY,
|
||||
RSN = 48,
|
||||
EXT_SUPPORTED_RATES = 50,
|
||||
AP_CHANNEL_REPORT,
|
||||
NEIGHBOR_REPORT,
|
||||
RCPI,
|
||||
MOBILITY_DOMAIN_MDE,
|
||||
FAST_BSS_TRANSITION_FTE,
|
||||
TIMEOUT_INTERVAL,
|
||||
RIC_DATA_RDE,
|
||||
DSE_REG_LOC,
|
||||
SUPPORTED_OP_CLASSES,
|
||||
EXT_CH_SWITCH_ANNOUNCEMENT,
|
||||
HT_OPERATION,
|
||||
SEC_CH_OFFSET,
|
||||
BSS_AVG_ACCESS_DELAY,
|
||||
ANTENNA,
|
||||
RSNI,
|
||||
MEASUREMENT_PILOT_TRANSMISSION,
|
||||
BSS_AVAIL_ADMISSION_CAPACITY,
|
||||
BSS_AC_ACCESS_DELAY,
|
||||
TIME_ADVERTISEMENT,
|
||||
RM_ENABLED_CAP,
|
||||
MULTIPLE_BSSID,
|
||||
BSS_2040_COEX,
|
||||
BSS_2040_INTOLERANT_CH_REPORT,
|
||||
OVERLAPPING_BSS_SCAN_PARAM,
|
||||
RIC_DESCRIPTOR,
|
||||
MGMT_MIC,
|
||||
EVENT_REQ = 78,
|
||||
EVENT_REPORT,
|
||||
DIAG_REQ,
|
||||
DIAG_REPORT,
|
||||
LOCATION_PARAMS,
|
||||
NONTRANSMITTED_BSSID_CAP,
|
||||
SSID_LIST,
|
||||
MULTIPLE_BSSID_INDEX,
|
||||
FMS_DESCRIPTOR,
|
||||
FMS_REQ,
|
||||
FMS_RESP,
|
||||
QOS_TRAFFIC_CAP,
|
||||
BSS_MAX_IDLE_PERIOD,
|
||||
TFS_REQ,
|
||||
TFS_RESP,
|
||||
WNM_SLEEP_MODE,
|
||||
TIM_BROADCAST_REQ,
|
||||
TIM_BROADCAST_RESP,
|
||||
COLLOCATED_INTERFERENCE_REPORT,
|
||||
CH_USAGE,
|
||||
TIME_ZONE,
|
||||
DMS_REQ,
|
||||
DMS_RESP,
|
||||
LINK_ID,
|
||||
WAKEUP_SCHEDULE,
|
||||
CH_SWITCH_TIMING,
|
||||
PTI_CONTROL,
|
||||
TPU_BUFFER_STATUS,
|
||||
INTERWORKING,
|
||||
ADVERTISEMENT_PROTOCOL,
|
||||
EXPEDITED_BANDWIDTH_REQ,
|
||||
QOS_MAP,
|
||||
ROAMING_CONSORTIUM,
|
||||
EMERG_ALERT_ID,
|
||||
MESH_CONFIG,
|
||||
MESH_ID,
|
||||
MESH_LINK_METRIC_REPORT,
|
||||
CONGESTION_NOTIFICATION,
|
||||
MESH_PEERING_MGMT,
|
||||
MESH_CH_SWITCH_PARAMS,
|
||||
MESH_AWAKE_WINDOW,
|
||||
BEACON_TIMING,
|
||||
MCCAOP_SETUP_REQ,
|
||||
MCCAOP_SETUP_REPLY,
|
||||
MCCAOP_ADVERTISEMENT,
|
||||
MCCAOP_TEARDOWN,
|
||||
GANN,
|
||||
RANN,
|
||||
EXT_CAP,
|
||||
PREQ = 130,
|
||||
PREP,
|
||||
PERR,
|
||||
PXU = 137,
|
||||
PXUC,
|
||||
AUTH_MESH_PEER_EX,
|
||||
MIC,
|
||||
DEST_URI,
|
||||
UAPSD_COEX,
|
||||
DMG_WAKEUP_SCHEDULE,
|
||||
EXT_SCHEDULE,
|
||||
STA_AVAIL,
|
||||
DMG_TSPEC,
|
||||
NEXT_DMG_ATI,
|
||||
DMG_CAP,
|
||||
DMG_OP = 151,
|
||||
DMG_BSS_PARAM_CHG,
|
||||
DMG_BEAM_REFINEMENT,
|
||||
CH_MEASUREMENT_FEEDBACK,
|
||||
AWAKE_WINDOW = 157,
|
||||
MULTIBAND,
|
||||
ADDBA_ESXT,
|
||||
NEXTPCP_LIST,
|
||||
PCP_HANDOVER,
|
||||
DMG_LINK_MARGIN,
|
||||
SWITCHING_STREAM,
|
||||
SESSION_TRANSITION,
|
||||
DYNAMIC_TONE_PAIRING_REPORT,
|
||||
CLUSTER_REPORT,
|
||||
RELAY_CAP,
|
||||
RELAY_TRANSFER_PARAM_SET,
|
||||
BEAMLINK_MAINTENANCE,
|
||||
MULTIPLE_MAC_SUBLAYERS,
|
||||
UPID,
|
||||
DMG_LINK_ADAPTATION_ACK,
|
||||
MCCAOP_ADV_OVERVIEW = 174,
|
||||
QUIET_PERIOD_REQ,
|
||||
QUIET_PERIOD_RESP = 177,
|
||||
QMF_POLICY = 181,
|
||||
ECAPC_POLICY = 182,
|
||||
CLUSTER_TIME_OFFSET,
|
||||
INTRA_ACCESS_CAT_PRIORITY,
|
||||
SCS_DESCRIPTOR,
|
||||
QLOAD_REPORT,
|
||||
HCCA_TXOP_UPDATE_COUNT,
|
||||
HIGHER_LAYER_STREAM_ID,
|
||||
GCR_GROUP_ADDR,
|
||||
ANTENNA_SECTOR_ID_PATTERN,
|
||||
VHT_CAP,
|
||||
VHT_OP,
|
||||
EXT_BSS_LOAD,
|
||||
WIDE_BANDWIDTH_CH_SWITCH,
|
||||
TRANSMIT_POWER_ENVELOPE,
|
||||
CH_SWITCH_WRAPPER,
|
||||
AID,
|
||||
QUIET_CHANNEL,
|
||||
OP_MODE_NOTIFY,
|
||||
UPSIM,
|
||||
REDUCED_NEIGHBOR_REPORT,
|
||||
TVHT_OP,
|
||||
DEV_LOC = 204,
|
||||
WHITE_SPACE_MAP,
|
||||
FINE_TUNING_MEASUREMENT_PARAMS,
|
||||
VENDOR_SPECIFIC = 221
|
||||
};
|
||||
|
||||
@@ -187,7 +330,7 @@ public:
|
||||
*
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
*/
|
||||
Dot11(const address_type &dst_hw_addr = address_type());
|
||||
Dot11(const address_type& dst_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs 802.11 PDU from a buffer and adds all
|
||||
@@ -201,91 +344,124 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the protocol version field.
|
||||
*
|
||||
* \return The stored protocol version field.
|
||||
*/
|
||||
small_uint<2> protocol() const { return _header.control.protocol; }
|
||||
small_uint<2> protocol() const {
|
||||
return header_.control.protocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Type field.
|
||||
*
|
||||
* \return The stored Type field.
|
||||
*/
|
||||
small_uint<2> type() const { return _header.control.type; }
|
||||
small_uint<2> type() const {
|
||||
return header_.control.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Subtype field.
|
||||
*
|
||||
* \return The stored Subtype field.
|
||||
*/
|
||||
small_uint<4> subtype() const { return _header.control.subtype; }
|
||||
small_uint<4> subtype() const {
|
||||
return header_.control.subtype;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the To-DS field.
|
||||
*
|
||||
* \return The stored To-DS field.
|
||||
*/
|
||||
small_uint<1> to_ds() const { return _header.control.to_ds; }
|
||||
small_uint<1> to_ds() const {
|
||||
return header_.control.to_ds;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the From-DS field.
|
||||
*
|
||||
* \return The stored From-DS field.
|
||||
*/
|
||||
small_uint<1> from_ds() const { return _header.control.from_ds; }
|
||||
small_uint<1> from_ds() const {
|
||||
return header_.control.from_ds;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the More-Frag field.
|
||||
*
|
||||
* \return The stored More-Frag field.
|
||||
*/
|
||||
small_uint<1> more_frag() const { return _header.control.more_frag; }
|
||||
small_uint<1> more_frag() const {
|
||||
return header_.control.more_frag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Retry field.
|
||||
*
|
||||
* \return The stored Retry field.
|
||||
*/
|
||||
small_uint<1> retry() const { return _header.control.retry; }
|
||||
small_uint<1> retry() const {
|
||||
return header_.control.retry;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Power-Management field.
|
||||
*
|
||||
* \return The stored Power-Management field.
|
||||
*/
|
||||
small_uint<1> power_mgmt() const { return _header.control.power_mgmt; }
|
||||
small_uint<1> power_mgmt() const {
|
||||
return header_.control.power_mgmt;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the More Data field.
|
||||
*
|
||||
* \return The stored More Data field.
|
||||
*/
|
||||
small_uint<1> more_data() const {
|
||||
return header_.control.more_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the WEP field.
|
||||
*
|
||||
* \return The stored WEP field.
|
||||
*/
|
||||
small_uint<1> wep() const { return _header.control.wep; }
|
||||
small_uint<1> wep() const {
|
||||
return header_.control.wep;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Order field.
|
||||
*
|
||||
* \return The stored Order field.
|
||||
*/
|
||||
small_uint<1> order() const { return _header.control.order; }
|
||||
small_uint<1> order() const {
|
||||
return header_.control.order;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Duration-ID field.
|
||||
*
|
||||
* \return The stored Duration-ID field.
|
||||
*/
|
||||
uint16_t duration_id() const { return Endian::le_to_host(_header.duration_id); }
|
||||
uint16_t duration_id() const {
|
||||
return Endian::le_to_host(header_.duration_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the first address.
|
||||
*
|
||||
* \return The stored first address.
|
||||
*/
|
||||
address_type addr1() const { return _header.addr1; }
|
||||
address_type addr1() const {
|
||||
return header_.addr1;
|
||||
}
|
||||
|
||||
// Setters
|
||||
|
||||
@@ -345,6 +521,13 @@ public:
|
||||
*/
|
||||
void power_mgmt(small_uint<1> new_value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the More Data field.
|
||||
*
|
||||
* \param new_value The new More Data field value.
|
||||
*/
|
||||
void more_data(small_uint<1> new_value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the WEP field.
|
||||
*
|
||||
@@ -371,7 +554,7 @@ public:
|
||||
*
|
||||
* \param new_addr1 The new first address.
|
||||
*/
|
||||
void addr1(const address_type &new_addr1);
|
||||
void addr1(const address_type& new_addr1);
|
||||
|
||||
/* Virtual methods */
|
||||
/**
|
||||
@@ -382,18 +565,18 @@ public:
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
#ifndef WIN32
|
||||
#ifndef _WIN32
|
||||
/**
|
||||
* \sa PDU::send()
|
||||
*/
|
||||
void send(PacketSender &sender, const NetworkInterface &iface);
|
||||
#endif // WIN32
|
||||
void send(PacketSender& sender, const NetworkInterface& iface);
|
||||
#endif // _WIN32
|
||||
|
||||
/**
|
||||
* \brief Adds a new option to this Dot11 PDU.
|
||||
* \param opt The option to be added.
|
||||
*/
|
||||
void add_option(const option &opt);
|
||||
void add_option(const option& opt);
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
/**
|
||||
@@ -405,35 +588,48 @@ public:
|
||||
*/
|
||||
void add_option(option &&opt) {
|
||||
internal_add_option(opt);
|
||||
_options.push_back(std::move(opt));
|
||||
options_.push_back(std::move(opt));
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Removes a Dot11 option.
|
||||
*
|
||||
* If there are multiple options of the given type, only the first one
|
||||
* will be removed.
|
||||
*
|
||||
* \param type The type of the option to be removed.
|
||||
* \return true if the option was removed, false otherwise.
|
||||
*/
|
||||
bool remove_option(OptionTypes type);
|
||||
|
||||
/**
|
||||
* \brief Looks up a tagged option in the option list.
|
||||
*
|
||||
* The returned pointer <b>must not</b> be free'd.
|
||||
*
|
||||
* \param opt The option identifier.
|
||||
* \param type The option identifier.
|
||||
* \return The option found, or 0 if no such option has been set.
|
||||
*/
|
||||
const option *search_option(OptionTypes opt) const;
|
||||
const option* search_option(OptionTypes type) const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11 *clone() const {
|
||||
Dot11* clone() const {
|
||||
return new Dot11(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -446,7 +642,9 @@ public:
|
||||
*
|
||||
* \return The options list.
|
||||
*/
|
||||
const options_type &options() const { return _options; }
|
||||
const options_type& options() const {
|
||||
return options_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Allocates an Dot11 PDU from a buffer.
|
||||
@@ -462,18 +660,18 @@ public:
|
||||
* \param total_sz The total size of the buffer.
|
||||
* \return The allocated Dot11 PDU.
|
||||
*/
|
||||
static Dot11 *from_bytes(const uint8_t *buffer, uint32_t total_sz);
|
||||
static Dot11* from_bytes(const uint8_t* buffer, uint32_t total_sz);
|
||||
protected:
|
||||
virtual uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz) { return 0; }
|
||||
virtual uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) { return 0; }
|
||||
void parse_tagged_parameters(const uint8_t *buffer, uint32_t total_sz);
|
||||
void add_tagged_option(OptionTypes opt, uint8_t len, const uint8_t *val);
|
||||
virtual void write_ext_header(Memory::OutputMemoryStream& stream);
|
||||
virtual void write_fixed_parameters(Memory::OutputMemoryStream& stream);
|
||||
void parse_tagged_parameters(Memory::InputMemoryStream& stream);
|
||||
void add_tagged_option(OptionTypes opt, uint8_t len, const uint8_t* val);
|
||||
protected:
|
||||
/**
|
||||
* Struct that represents the 802.11 header
|
||||
*/
|
||||
TINS_BEGIN_PACK
|
||||
struct ieee80211_header {
|
||||
struct dot11_header {
|
||||
TINS_BEGIN_PACK
|
||||
struct {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
@@ -507,16 +705,19 @@ protected:
|
||||
|
||||
} TINS_END_PACK;
|
||||
private:
|
||||
Dot11(const ieee80211_header *header_ptr);
|
||||
Dot11(const dot11_header* header_ptr);
|
||||
|
||||
void internal_add_option(const option &opt);
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
void internal_add_option(const option& opt);
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz);
|
||||
options_type::const_iterator search_option_iterator(OptionTypes type) const;
|
||||
options_type::iterator search_option_iterator(OptionTypes type);
|
||||
|
||||
|
||||
ieee80211_header _header;
|
||||
uint32_t _options_size;
|
||||
options_type _options;
|
||||
dot11_header header_;
|
||||
uint32_t options_size_;
|
||||
options_type options_;
|
||||
};
|
||||
}
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_DOT11_DOT11_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -27,140 +27,153 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../config.h"
|
||||
#include <tins/config.h>
|
||||
|
||||
#if !defined(TINS_DOT11_DOT11_BEACON_H) && defined(HAVE_DOT11)
|
||||
#if !defined(TINS_DOT11_DOT11_BEACON_H) && defined(TINS_HAVE_DOT11)
|
||||
#define TINS_DOT11_DOT11_BEACON_H
|
||||
|
||||
#include "../dot11/dot11_mgmt.h"
|
||||
#include <tins/dot11/dot11_mgmt.h>
|
||||
#include <tins/macros.h>
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \brief Represents an IEEE 802.11 Beacon.
|
||||
*
|
||||
*/
|
||||
class TINS_API Dot11Beacon : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief Class representing an 802.11 Beacon.
|
||||
*
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
class Dot11Beacon : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_BEACON;
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_BEACON;
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 Beacon.
|
||||
*
|
||||
* Constructs a 802.11 Beacon taking destination and source
|
||||
* hardware address.
|
||||
*
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11Beacon(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 Beacon.
|
||||
*
|
||||
* Constructs a 802.11 Beacon taking destination and source
|
||||
* hardware address.
|
||||
*
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11Beacon(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11Beacon object from a buffer and adds
|
||||
* all identifiable PDUs found in the buffer as children of this
|
||||
* one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, a malformed_packet exception
|
||||
* is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11Beacon(const uint8_t *buffer, uint32_t total_sz);
|
||||
/**
|
||||
* \brief Constructs a Dot11Beacon object from a buffer and adds
|
||||
* all identifiable PDUs found in the buffer as children of this
|
||||
* one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, a malformed_packet exception
|
||||
* is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11Beacon(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the timestamp field.
|
||||
*
|
||||
* \return The stored timestamp value.
|
||||
*/
|
||||
uint64_t timestamp() const { return Endian::le_to_host(_body.timestamp); }
|
||||
/**
|
||||
* \brief Getter for the timestamp field.
|
||||
*
|
||||
* \return The stored timestamp value.
|
||||
*/
|
||||
uint64_t timestamp() const {
|
||||
return Endian::le_to_host(body_.timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the interval field.
|
||||
*
|
||||
* \return The stored interval value.
|
||||
*/
|
||||
uint16_t interval() const { return Endian::le_to_host(_body.interval); }
|
||||
/**
|
||||
* \brief Getter for the interval field.
|
||||
*
|
||||
* \return The stored interval value.
|
||||
*/
|
||||
uint16_t interval() const {
|
||||
return Endian::le_to_host(body_.interval);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information structure.
|
||||
*
|
||||
* \return A constant refereence to the stored Capabilities
|
||||
* Information field.
|
||||
*/
|
||||
const capability_information& capabilities() const { return _body.capability; }
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information structure.
|
||||
*
|
||||
* \return A constant refereence to the stored Capabilities
|
||||
* Information field.
|
||||
*/
|
||||
const capability_information& capabilities() const {
|
||||
return body_.capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
*
|
||||
* \return A refereence to the stored Capabilities Information
|
||||
* field.
|
||||
*/
|
||||
capability_information& capabilities() { return _body.capability; }
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
*
|
||||
* \return A refereence to the stored Capabilities Information
|
||||
* field.
|
||||
*/
|
||||
capability_information& capabilities() {
|
||||
return body_.capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the timestamp field.
|
||||
*
|
||||
* \param new_timestamp The timestamp to be set.
|
||||
*/
|
||||
void timestamp(uint64_t new_timestamp);
|
||||
/**
|
||||
* \brief Setter for the timestamp field.
|
||||
*
|
||||
* \param new_timestamp The timestamp to be set.
|
||||
*/
|
||||
void timestamp(uint64_t new_timestamp);
|
||||
|
||||
/**
|
||||
* \brief Setter for the interval field.
|
||||
*
|
||||
* \param new_interval The interval to be set.
|
||||
*/
|
||||
void interval(uint16_t new_interval);
|
||||
/**
|
||||
* \brief Setter for the interval field.
|
||||
*
|
||||
* \param new_interval The interval to be set.
|
||||
*/
|
||||
void interval(uint16_t new_interval);
|
||||
|
||||
/**
|
||||
* \brief Returns the frame's header length.
|
||||
*
|
||||
* \return An uint32_t with the header's size.
|
||||
* \sa PDU::header_size()
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
/**
|
||||
* \brief Returns the frame's header length.
|
||||
*
|
||||
* \return An uint32_t with the header's size.
|
||||
* \sa PDU::header_size()
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
|
||||
}
|
||||
/**
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11Beacon *clone() const {
|
||||
return new Dot11Beacon(*this);
|
||||
}
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11Beacon* clone() const {
|
||||
return new Dot11Beacon(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct BeaconBody {
|
||||
uint64_t timestamp;
|
||||
uint16_t interval;
|
||||
capability_information capability;
|
||||
} TINS_END_PACK;
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct dot11_beacon_body {
|
||||
uint64_t timestamp;
|
||||
uint16_t interval;
|
||||
capability_information capability;
|
||||
} TINS_END_PACK;
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
|
||||
|
||||
dot11_beacon_body body_;
|
||||
};
|
||||
|
||||
BeaconBody _body;
|
||||
};
|
||||
} // namespace Tins
|
||||
|
||||
#endif // TINS_DOT11_DOT11_BEACON_H
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
@@ -27,64 +27,67 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../config.h"
|
||||
#include <tins/config.h>
|
||||
|
||||
#if !defined(TINS_DOT11_DOT11_CONTROL_H) && defined(HAVE_DOT11)
|
||||
#if !defined(TINS_DOT11_DOT11_CONTROL_H) && defined(TINS_HAVE_DOT11)
|
||||
|
||||
#define TINS_DOT11_DOT11_CONTROL_H
|
||||
|
||||
#include "../dot11/dot11_base.h"
|
||||
#include <tins/dot11/dot11_base.h>
|
||||
#include <tins/macros.h>
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \brief Class that represents an 802.11 control frame.
|
||||
* \brief Represents an IEEE 802.11 control frame.
|
||||
*/
|
||||
class Dot11Control : public Dot11 {
|
||||
class TINS_API Dot11Control : public Dot11 {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_CONTROL;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 control frame PDU
|
||||
*
|
||||
* Constructs a 802.11 Control PDU taking the destination and
|
||||
* Constructs a 802.11 Control PDU taking the destination and
|
||||
* source hardware addresses.
|
||||
*
|
||||
* \param dst_addr The destination hardware address.
|
||||
*/
|
||||
Dot11Control(const address_type &dst_addr = address_type());
|
||||
Dot11Control(const address_type& dst_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11Control object from a buffer and
|
||||
* adds all identifiable PDUs found in the buffer as children
|
||||
* adds all identifiable PDUs found in the buffer as children
|
||||
* of this one.
|
||||
*
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, a malformed_packet exception
|
||||
* or the input data is malformed, a malformed_packet exception
|
||||
* is thrown.
|
||||
*
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11Control(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11Control(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::DOT11_CONTROL; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == PDU::DOT11_CONTROL || Dot11::matches_flag(flag);
|
||||
return flag == pdu_flag || Dot11::matches_flag(flag);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -92,46 +95,62 @@ public:
|
||||
* \brief Class that represents an abstraction of the 802.11 control frames
|
||||
* that contain a target address.
|
||||
*/
|
||||
class Dot11ControlTA : public Dot11Control {
|
||||
class TINS_API Dot11ControlTA : public Dot11Control {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_CONTROL_TA;
|
||||
|
||||
/**
|
||||
* \brief Getter for the target address field.
|
||||
*/
|
||||
address_type target_addr() const { return _taddr; }
|
||||
address_type target_addr() const {
|
||||
return taddr_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the target address field.
|
||||
* \param addr The new target address.
|
||||
*/
|
||||
void target_addr(const address_type &addr);
|
||||
void target_addr(const address_type& addr);
|
||||
|
||||
/**
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11::matches_flag(flag);
|
||||
}
|
||||
protected:
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 control frame TA PDU
|
||||
*
|
||||
* Constructs a 802.11 PDU taking the destination and source
|
||||
* Constructs a 802.11 PDU taking the destination and source
|
||||
* hardware addresses.
|
||||
*
|
||||
* \param dst_addr The destination hardware address.
|
||||
* \param target_addr The source hardware address.
|
||||
*/
|
||||
Dot11ControlTA(const address_type &dst_addr = address_type(),
|
||||
const address_type &target_addr = address_type());
|
||||
Dot11ControlTA(const address_type& dst_addr = address_type(),
|
||||
const address_type& target_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11ControlTA object from a buffer and
|
||||
* adds all identifiable PDUs found in the buffer as children
|
||||
* adds all identifiable PDUs found in the buffer as children
|
||||
* of this one.
|
||||
*
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, a malformed_packet exception
|
||||
* or the input data is malformed, a malformed_packet exception
|
||||
* is thrown.
|
||||
*
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11ControlTA(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11ControlTA(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Returns the 802.11 frame's header length.
|
||||
@@ -144,18 +163,20 @@ protected:
|
||||
/**
|
||||
* \brief Getter for the control ta additional fields size.
|
||||
*/
|
||||
uint32_t controlta_size() const { return _taddr.size() + sizeof(ieee80211_header); }
|
||||
uint32_t controlta_size() const {
|
||||
return static_cast<uint32_t>(taddr_.size() + sizeof(dot11_header));
|
||||
}
|
||||
|
||||
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_ext_header(Memory::OutputMemoryStream& stream);
|
||||
private:
|
||||
|
||||
address_type _taddr;
|
||||
address_type taddr_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief IEEE 802.11 RTS frame.
|
||||
*/
|
||||
class Dot11RTS : public Dot11ControlTA {
|
||||
class TINS_API Dot11RTS : public Dot11ControlTA {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -171,30 +192,30 @@ public:
|
||||
* \param dst_addr The destination hardware address.
|
||||
* \param target_addr The source hardware address.
|
||||
*/
|
||||
Dot11RTS(const address_type &dst_addr = address_type(),
|
||||
const address_type &target_addr = address_type());
|
||||
|
||||
Dot11RTS(const address_type& dst_addr = address_type(),
|
||||
const address_type& target_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11RTS object from a buffer and adds all
|
||||
* \brief Constructs a Dot11RTS object from a buffer and adds all
|
||||
* identifiable PDUs found in the buffer as children of this one.
|
||||
*
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, a malformed_packet exception
|
||||
* or the input data is malformed, a malformed_packet exception
|
||||
* is thrown.
|
||||
*
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11RTS(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11RTS(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11RTS *clone() const {
|
||||
Dot11RTS* clone() const {
|
||||
return new Dot11RTS(*this);
|
||||
}
|
||||
|
||||
@@ -202,10 +223,12 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -214,7 +237,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class Dot11PSPoll : public Dot11ControlTA {
|
||||
class TINS_API Dot11PSPoll : public Dot11ControlTA {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -224,37 +247,37 @@ public:
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 PS-Poll frame PDU
|
||||
*
|
||||
* Constructs a 802.11 PDU taking the destination and source
|
||||
* Constructs a 802.11 PDU taking the destination and source
|
||||
* hardware addresses.
|
||||
*
|
||||
* \param dst_addr The destination hardware address.
|
||||
* \param target_addr The source hardware address.
|
||||
*/
|
||||
Dot11PSPoll(const address_type &dst_addr = address_type(),
|
||||
const address_type &target_addr = address_type());
|
||||
Dot11PSPoll(const address_type& dst_addr = address_type(),
|
||||
const address_type& target_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11PSPoll object from a buffer and
|
||||
* adds all identifiable PDUs found in the buffer as children of
|
||||
* adds all identifiable PDUs found in the buffer as children of
|
||||
* this one.
|
||||
*
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, a malformed_packet exception
|
||||
* or the input data is malformed, a malformed_packet exception
|
||||
* is thrown.
|
||||
*
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11PSPoll(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11PSPoll(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11PSPoll *clone() const {
|
||||
Dot11PSPoll* clone() const {
|
||||
return new Dot11PSPoll(*this);
|
||||
}
|
||||
|
||||
@@ -262,10 +285,12 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -274,7 +299,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class Dot11CFEnd : public Dot11ControlTA {
|
||||
class TINS_API Dot11CFEnd : public Dot11ControlTA {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -284,37 +309,37 @@ public:
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 CF-End frame PDU
|
||||
*
|
||||
* Constructs a 802.11 PDU taking the destination and source
|
||||
* Constructs a 802.11 PDU taking the destination and source
|
||||
* hardware addresses.
|
||||
*
|
||||
* \param dst_addr The destination hardware address.
|
||||
* \param target_addr The source hardware address.
|
||||
*/
|
||||
Dot11CFEnd(const address_type &dst_addr = address_type(),
|
||||
const address_type &target_addr = address_type());
|
||||
|
||||
Dot11CFEnd(const address_type& dst_addr = address_type(),
|
||||
const address_type& target_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11CFEnd object from a buffer and adds
|
||||
* all identifiable PDUs found in the buffer as children of this
|
||||
* \brief Constructs a Dot11CFEnd object from a buffer and adds
|
||||
* all identifiable PDUs found in the buffer as children of this
|
||||
* one.
|
||||
*
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, a malformed_packet exception
|
||||
* or the input data is malformed, a malformed_packet exception
|
||||
* is thrown.
|
||||
*
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11CFEnd(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11CFEnd(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11CFEnd *clone() const {
|
||||
Dot11CFEnd* clone() const {
|
||||
return new Dot11CFEnd(*this);
|
||||
}
|
||||
|
||||
@@ -322,19 +347,21 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
}
|
||||
};
|
||||
|
||||
class Dot11EndCFAck : public Dot11ControlTA {
|
||||
class TINS_API Dot11EndCFAck : public Dot11ControlTA {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -344,37 +371,37 @@ public:
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 End-CF-Ack frame PDU
|
||||
*
|
||||
* Constructs a 802.11 PDU taking the destination and source
|
||||
* Constructs a 802.11 PDU taking the destination and source
|
||||
* hardware addresses.
|
||||
*
|
||||
*
|
||||
* \param dst_addr The destination hardware address.
|
||||
* \param target_addr The source hardware address.
|
||||
*/
|
||||
Dot11EndCFAck(const address_type &dst_addr = address_type(),
|
||||
const address_type &target_addr = address_type());
|
||||
Dot11EndCFAck(const address_type& dst_addr = address_type(),
|
||||
const address_type& target_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11EndCFAck frame object from a buffer
|
||||
* and adds all identifiable PDUs found in the buffer as children
|
||||
* \brief Constructs a Dot11EndCFAck frame object from a buffer
|
||||
* and adds all identifiable PDUs found in the buffer as children
|
||||
* of this one.
|
||||
*
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, a malformed_packet exception
|
||||
* or the input data is malformed, a malformed_packet exception
|
||||
* is thrown.
|
||||
*
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11EndCFAck(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11EndCFAck(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11EndCFAck *clone() const {
|
||||
Dot11EndCFAck* clone() const {
|
||||
return new Dot11EndCFAck(*this);
|
||||
}
|
||||
|
||||
@@ -382,19 +409,21 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
}
|
||||
};
|
||||
|
||||
class Dot11Ack : public Dot11Control {
|
||||
class TINS_API Dot11Ack : public Dot11Control {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -404,35 +433,35 @@ public:
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 Ack frame PDU
|
||||
*
|
||||
* Constructs a 802.11 PDU taking the destination and source
|
||||
* Constructs a 802.11 PDU taking the destination and source
|
||||
* hardware addresses.
|
||||
*
|
||||
* \param dst_addr The destination hardware address.
|
||||
*/
|
||||
Dot11Ack(const address_type &dst_addr = address_type());
|
||||
Dot11Ack(const address_type& dst_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11Ack frame object from a buffer and
|
||||
* adds all identifiable PDUs found in the buffer as children of
|
||||
* adds all identifiable PDUs found in the buffer as children of
|
||||
* this one.
|
||||
*
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, a malformed_packet exception
|
||||
* or the input data is malformed, a malformed_packet exception
|
||||
* is thrown.
|
||||
*
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11Ack(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11Ack(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Clones this PDU.
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11Ack *clone() const {
|
||||
Dot11Ack* clone() const {
|
||||
return new Dot11Ack(*this);
|
||||
}
|
||||
|
||||
@@ -440,22 +469,24 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Class that represents an 802.11 Block Ack Request PDU.
|
||||
*/
|
||||
class Dot11BlockAckRequest : public Dot11ControlTA {
|
||||
class TINS_API Dot11BlockAckRequest : public Dot11ControlTA {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -465,30 +496,30 @@ public:
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 Block Ack request frame PDU
|
||||
*
|
||||
* Constructs a 802.11 PDU taking the destination and source
|
||||
* Constructs a 802.11 PDU taking the destination and source
|
||||
* hardware addresses.
|
||||
*
|
||||
*
|
||||
* \param dst_addr The destination hardware address.
|
||||
* \param target_addr The source hardware address.
|
||||
*/
|
||||
Dot11BlockAckRequest(const address_type &dst_addr = address_type(),
|
||||
const address_type &target_addr = address_type());
|
||||
Dot11BlockAckRequest(const address_type& dst_addr = address_type(),
|
||||
const address_type& target_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11BlockAckRequest object from a buffer
|
||||
* and adds all identifiable PDUs found in the buffer as children
|
||||
* \brief Constructs a Dot11BlockAckRequest object from a buffer
|
||||
* and adds all identifiable PDUs found in the buffer as children
|
||||
* of this one.
|
||||
*
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, a malformed_packet exception
|
||||
* or the input data is malformed, a malformed_packet exception
|
||||
* is thrown.
|
||||
*
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11BlockAckRequest(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11BlockAckRequest(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/* Getter */
|
||||
|
||||
@@ -496,11 +527,11 @@ public:
|
||||
* \brief Getter for the bar control field.
|
||||
* \return The stored bar control field.
|
||||
*/
|
||||
small_uint<4> bar_control() const {
|
||||
small_uint<4> bar_control() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return _bar_control & 0xf;
|
||||
return bar_control_ & 0xf;
|
||||
#else
|
||||
return (_bar_control >> 8) & 0xf;
|
||||
return (bar_control_ >> 8) & 0xf;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -508,26 +539,26 @@ public:
|
||||
* \brief Getter for the start sequence field.
|
||||
* \return The stored start sequence.
|
||||
*/
|
||||
small_uint<12> start_sequence() const {
|
||||
small_uint<12> start_sequence() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return (_start_sequence >> 4) & 0xfff;
|
||||
return (start_sequence_ >> 4) & 0xfff;
|
||||
#else
|
||||
return (Endian::le_to_host<uint16_t>(_start_sequence) >> 4) & 0xfff;
|
||||
return (Endian::le_to_host<uint16_t>(start_sequence_) >> 4) & 0xfff;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Getter for the fragment number field.
|
||||
* \return The stored fragment number field.
|
||||
*/
|
||||
small_uint<4> fragment_number() const {
|
||||
small_uint<4> fragment_number() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return _start_sequence & 0xf;
|
||||
return start_sequence_ & 0xf;
|
||||
#else
|
||||
return (_start_sequence >> 8) & 0xf;
|
||||
return (start_sequence_ >> 8) & 0xf;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Returns the 802.11 frame's header length.
|
||||
*
|
||||
@@ -549,7 +580,7 @@ public:
|
||||
* \param bar The start sequence field to be set.
|
||||
*/
|
||||
void start_sequence(small_uint<12> seq);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Setter for the fragment number field.
|
||||
* \param frag The fragment number field to be set.
|
||||
@@ -561,7 +592,7 @@ public:
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11BlockAckRequest *clone() const {
|
||||
Dot11BlockAckRequest* clone() const {
|
||||
return new Dot11BlockAckRequest(*this);
|
||||
}
|
||||
|
||||
@@ -569,35 +600,35 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
}
|
||||
protected:
|
||||
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_ext_header(Memory::OutputMemoryStream& stream);
|
||||
private:
|
||||
void init_block_ack();
|
||||
|
||||
uint16_t _bar_control;
|
||||
uint16_t _start_sequence;
|
||||
uint16_t bar_control_;
|
||||
uint16_t start_sequence_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Class that represents an 802.11 block ack frame.
|
||||
*/
|
||||
class Dot11BlockAck : public Dot11ControlTA {
|
||||
class TINS_API Dot11BlockAck : public Dot11ControlTA {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_BLOCK_ACK;
|
||||
|
||||
|
||||
/**
|
||||
* The size of the bitmap field.
|
||||
*/
|
||||
@@ -606,30 +637,30 @@ public:
|
||||
/**
|
||||
* \brief Constructor for creating a 802.11 Block Ack frame PDU
|
||||
*
|
||||
* Constructs a 802.11 PDU taking the destination and source
|
||||
* Constructs a 802.11 PDU taking the destination and source
|
||||
* hardware addresses.
|
||||
*
|
||||
*
|
||||
* \param dst_addr The destination hardware address.
|
||||
* \param target_addr The source hardware address.
|
||||
*/
|
||||
Dot11BlockAck(const address_type &dst_addr = address_type(),
|
||||
const address_type &target_addr = address_type());
|
||||
Dot11BlockAck(const address_type& dst_addr = address_type(),
|
||||
const address_type& target_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11BlockAck frame object from a buffer
|
||||
* and adds all identifiable PDUs found in the buffer as children
|
||||
* \brief Constructs a Dot11BlockAck frame object from a buffer
|
||||
* and adds all identifiable PDUs found in the buffer as children
|
||||
* of this one.
|
||||
*
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
*
|
||||
* If there is not enough size for the header in the buffer
|
||||
* or the input data is malformed, a malformed_packet exception
|
||||
* or the input data is malformed, a malformed_packet exception
|
||||
* is thrown.
|
||||
*
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11BlockAck(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11BlockAck(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/* Getters */
|
||||
|
||||
@@ -637,11 +668,11 @@ public:
|
||||
* \brief Getter for the bar control field.
|
||||
* \return The stored bar control field.
|
||||
*/
|
||||
small_uint<4> bar_control() const {
|
||||
small_uint<4> bar_control() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return _bar_control & 0xf;
|
||||
return bar_control_ & 0xf;
|
||||
#else
|
||||
return (_bar_control >> 8) & 0xf;
|
||||
return (bar_control_ >> 8) & 0xf;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -649,26 +680,26 @@ public:
|
||||
* \brief Getter for the start sequence field.
|
||||
* \return The stored start sequence.
|
||||
*/
|
||||
small_uint<12> start_sequence() const {
|
||||
small_uint<12> start_sequence() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return (_start_sequence >> 4) & 0xfff;
|
||||
return (start_sequence_ >> 4) & 0xfff;
|
||||
#else
|
||||
return (Endian::le_to_host<uint16_t>(_start_sequence) >> 4) & 0xfff;
|
||||
return (Endian::le_to_host<uint16_t>(start_sequence_) >> 4) & 0xfff;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Getter for the fragment number field.
|
||||
* \return The stored fragment number field.
|
||||
*/
|
||||
small_uint<4> fragment_number() const {
|
||||
small_uint<4> fragment_number() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return _start_sequence & 0xf;
|
||||
return start_sequence_ & 0xf;
|
||||
#else
|
||||
return (_start_sequence >> 8) & 0xf;
|
||||
return (start_sequence_ >> 8) & 0xf;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Returns the 802.11 frame's header length.
|
||||
*
|
||||
@@ -690,7 +721,7 @@ public:
|
||||
* \param bar The start sequence field to be set.
|
||||
*/
|
||||
void start_sequence(small_uint<12> seq);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Setter for the fragment number field.
|
||||
* \param frag The fragment number field to be set.
|
||||
@@ -699,32 +730,36 @@ public:
|
||||
|
||||
/**
|
||||
* \brief Getter for the bitmap field.
|
||||
*
|
||||
*
|
||||
* The returned pointer <b>must not</b> be free'd.
|
||||
*
|
||||
*
|
||||
* \return The bitmap field.
|
||||
*/
|
||||
const uint8_t *bitmap() const { return _bitmap; }
|
||||
const uint8_t* bitmap() const {
|
||||
return bitmap_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the bitmap field.
|
||||
* \param bit The new bitmap field to be set.
|
||||
*/
|
||||
void bitmap(const uint8_t *bit);
|
||||
void bitmap(const uint8_t* bit);
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
return flag == pdu_flag || Dot11Control::matches_flag(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -732,15 +767,16 @@ public:
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11BlockAck *clone() const {
|
||||
Dot11BlockAck* clone() const {
|
||||
return new Dot11BlockAck(*this);
|
||||
}
|
||||
private:
|
||||
void init_block_ack();
|
||||
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_ext_header(Memory::OutputMemoryStream& stream);
|
||||
|
||||
uint16_t _bar_control, _start_sequence;
|
||||
uint8_t _bitmap[bitmap_size];
|
||||
uint16_t bar_control_, start_sequence_;
|
||||
uint8_t bitmap_[bitmap_size];
|
||||
};
|
||||
|
||||
} // namespace Tins
|
||||
|
||||
#endif // TINS_DOT11_DOT11_CONTROL_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -27,15 +27,20 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../config.h"
|
||||
#include <tins/config.h>
|
||||
|
||||
#if !defined(TINS_DOT11_DOT11_DATA_H) && defined(HAVE_DOT11)
|
||||
#if !defined(TINS_DOT11_DOT11_DATA_H) && defined(TINS_HAVE_DOT11)
|
||||
#define TINS_DOT11_DOT11_DATA_H
|
||||
|
||||
#include "../dot11/dot11_base.h"
|
||||
#include <tins/dot11/dot11_base.h>
|
||||
#include <tins/macros.h>
|
||||
|
||||
namespace Tins {
|
||||
class Dot11Data : public Dot11 {
|
||||
|
||||
/**
|
||||
* \brief Represents an IEEE 802.11 data frame
|
||||
*/
|
||||
class TINS_API Dot11Data : public Dot11 {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -51,8 +56,8 @@ public:
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11Data(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
Dot11Data(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11Data object from a buffer and adds
|
||||
@@ -68,21 +73,25 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11Data(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11Data(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the second address.
|
||||
*
|
||||
* \return The stored second address.
|
||||
*/
|
||||
address_type addr2() const { return _ext_header.addr2; }
|
||||
address_type addr2() const {
|
||||
return ext_header_.addr2;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the third address.
|
||||
*
|
||||
* \return The stored third address.
|
||||
*/
|
||||
address_type addr3() const { return _ext_header.addr3; }
|
||||
address_type addr3() const {
|
||||
return ext_header_.addr3;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the fragment number field.
|
||||
@@ -91,9 +100,9 @@ public:
|
||||
*/
|
||||
small_uint<4> frag_num() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return _ext_header.frag_seq & 0xf;
|
||||
return ext_header_.frag_seq & 0xf;
|
||||
#else
|
||||
return (_ext_header.frag_seq >> 8) & 0xf;
|
||||
return (ext_header_.frag_seq >> 8) & 0xf;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -104,9 +113,9 @@ public:
|
||||
*/
|
||||
small_uint<12> seq_num() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return (_ext_header.frag_seq >> 4) & 0xfff;
|
||||
return (ext_header_.frag_seq >> 4) & 0xfff;
|
||||
#else
|
||||
return (Endian::le_to_host<uint16_t>(_ext_header.frag_seq) >> 4) & 0xfff;
|
||||
return (Endian::le_to_host<uint16_t>(ext_header_.frag_seq) >> 4) & 0xfff;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -115,21 +124,23 @@ public:
|
||||
*
|
||||
* \return The fourth address.
|
||||
*/
|
||||
address_type addr4() const { return _addr4; }
|
||||
address_type addr4() const {
|
||||
return addr4_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the second address.
|
||||
*
|
||||
* \param new_addr2 The second address to be set.
|
||||
*/
|
||||
void addr2(const address_type &new_addr2);
|
||||
void addr2(const address_type& new_addr2);
|
||||
|
||||
/**
|
||||
* \brief Setter for the third address.
|
||||
*
|
||||
* \param new_addr3 The third address to be set.
|
||||
*/
|
||||
void addr3(const address_type &new_addr3);
|
||||
void addr3(const address_type& new_addr3);
|
||||
|
||||
/**
|
||||
* \brief Setter for the fragment number field.
|
||||
@@ -150,7 +161,7 @@ public:
|
||||
*
|
||||
* \param new_addr4 The fourth address to be set.
|
||||
*/
|
||||
void addr4(const address_type &new_addr4);
|
||||
void addr4(const address_type& new_addr4);
|
||||
|
||||
/**
|
||||
* \brief Retrieves the frame's source address.
|
||||
@@ -161,10 +172,12 @@ public:
|
||||
* If FromDS == ToDS == 1, the return value is not defined.
|
||||
*/
|
||||
address_type src_addr() const {
|
||||
if(!from_ds() && !to_ds())
|
||||
if (!from_ds() && !to_ds()) {
|
||||
return addr2();
|
||||
if(!from_ds() && to_ds())
|
||||
}
|
||||
if (!from_ds() && to_ds()) {
|
||||
return addr2();
|
||||
}
|
||||
return addr3();
|
||||
}
|
||||
|
||||
@@ -177,10 +190,12 @@ public:
|
||||
* If FromDS == ToDS == 1, the return value is not defined.
|
||||
*/
|
||||
address_type dst_addr() const {
|
||||
if(!from_ds() && !to_ds())
|
||||
if (!from_ds() && !to_ds()) {
|
||||
return addr1();
|
||||
if(!from_ds() && to_ds())
|
||||
}
|
||||
if (!from_ds() && to_ds()) {
|
||||
return addr3();
|
||||
}
|
||||
return addr1();
|
||||
}
|
||||
|
||||
@@ -193,10 +208,12 @@ public:
|
||||
* If FromDS == ToDS == 1, the return value is not defined.
|
||||
*/
|
||||
address_type bssid_addr() const {
|
||||
if(!from_ds() && !to_ds())
|
||||
if (!from_ds() && !to_ds()) {
|
||||
return addr3();
|
||||
if(!from_ds() && to_ds())
|
||||
}
|
||||
if (!from_ds() && to_ds()) {
|
||||
return addr1();
|
||||
}
|
||||
return addr2();
|
||||
}
|
||||
|
||||
@@ -212,10 +229,12 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -228,33 +247,28 @@ public:
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11Data *clone() const {
|
||||
Dot11Data* clone() const {
|
||||
return new Dot11Data(*this);
|
||||
}
|
||||
protected:
|
||||
TINS_BEGIN_PACK
|
||||
struct ExtendedHeader {
|
||||
struct dot11_extended_header {
|
||||
uint8_t addr2[address_type::address_size];
|
||||
uint8_t addr3[address_type::address_size];
|
||||
uint16_t frag_seq;
|
||||
} TINS_END_PACK;
|
||||
|
||||
struct no_inner_pdu { };
|
||||
Dot11Data(const uint8_t *buffer, uint32_t total_sz, no_inner_pdu);
|
||||
Dot11Data(const uint8_t* buffer, uint32_t total_sz, no_inner_pdu);
|
||||
|
||||
uint32_t init(const uint8_t *buffer, uint32_t total_sz);
|
||||
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
uint32_t data_frame_size() {
|
||||
return Dot11::header_size() + sizeof(_ext_header) +
|
||||
((from_ds() && to_ds()) ? _addr4.size() : 0);
|
||||
}
|
||||
uint32_t init(const uint8_t* buffer, uint32_t total_sz);
|
||||
void write_ext_header(Memory::OutputMemoryStream& stream);
|
||||
private:
|
||||
ExtendedHeader _ext_header;
|
||||
address_type _addr4;
|
||||
dot11_extended_header ext_header_;
|
||||
address_type addr4_;
|
||||
};
|
||||
|
||||
class Dot11QoSData : public Dot11Data {
|
||||
class TINS_API Dot11QoSData : public Dot11Data {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -270,8 +284,8 @@ public:
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11QoSData(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
Dot11QoSData(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructors Dot11QoSData object from a buffer and adds
|
||||
@@ -287,14 +301,16 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11QoSData(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11QoSData(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the QOS Control field.
|
||||
*
|
||||
* \return The stored QOS Control field value.
|
||||
*/
|
||||
uint16_t qos_control() const { return Endian::le_to_host(_qos_control); }
|
||||
uint16_t qos_control() const {
|
||||
return Endian::le_to_host(qos_control_);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the QOS Control field.
|
||||
@@ -316,7 +332,7 @@ public:
|
||||
*
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot11QoSData *clone() const {
|
||||
Dot11QoSData* clone() const {
|
||||
return new Dot11QoSData(*this);
|
||||
}
|
||||
|
||||
@@ -324,21 +340,22 @@ public:
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::DOT11_QOS_DATA; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == PDU::DOT11_QOS_DATA || Dot11Data::matches_flag(flag);
|
||||
return flag == pdu_flag || Dot11Data::matches_flag(flag);
|
||||
}
|
||||
private:
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
|
||||
|
||||
|
||||
uint16_t _qos_control;
|
||||
uint16_t qos_control_;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -27,21 +27,22 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../config.h"
|
||||
#include <tins/config.h>
|
||||
|
||||
#if !defined(TINS_DOT11_DOT11_MGMT_H) && defined(HAVE_DOT11)
|
||||
#if !defined(TINS_DOT11_DOT11_MGMT_H) && defined(TINS_HAVE_DOT11)
|
||||
|
||||
#define TINS_DOT11_DOT11_MGMT_H
|
||||
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include "../dot11/dot11_base.h"
|
||||
#include <tins/dot11/dot11_base.h>
|
||||
#include <tins/macros.h>
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \brief Abstract class that englobes all Management frames in the 802.11 protocol.
|
||||
* \brief Base class for all management frames in the IEEE 802.11 protocol.
|
||||
*/
|
||||
class Dot11ManagementFrame : public Dot11 {
|
||||
class TINS_API Dot11ManagementFrame : public Dot11 {
|
||||
public:
|
||||
/**
|
||||
* The supported rates container type.
|
||||
@@ -53,6 +54,11 @@ public:
|
||||
*/
|
||||
typedef std::vector<std::pair<uint8_t, uint8_t> > channels_type;
|
||||
|
||||
/**
|
||||
* The channel map container type.
|
||||
*/
|
||||
typedef std::vector<std::pair<uint8_t, uint8_t> > channel_map_type;
|
||||
|
||||
/**
|
||||
* The requested information container type.
|
||||
*/
|
||||
@@ -63,6 +69,12 @@ public:
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT11_MANAGEMENT;
|
||||
|
||||
/**
|
||||
* \brief Enum used in the reason code field.
|
||||
*
|
||||
* This enumeration can be used to get or set the reason code field in a
|
||||
* Deauthentication or Disassociation
|
||||
*/
|
||||
enum ReasonCodes {
|
||||
UNSPECIFIED = 1,
|
||||
PREV_AUTH_NOT_VALID = 2,
|
||||
@@ -97,6 +109,21 @@ public:
|
||||
REQUESTED_BY_STA_TIMEOUT = 39,
|
||||
PEER_STA_NOT_SUPPORT_CIPHER = 45
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Enum that represents the map field within a channels map field.
|
||||
*
|
||||
* These bitmasks can be used to get or set the second value of
|
||||
* ibss_dfs_params().channel_map
|
||||
*/
|
||||
enum MapMask {
|
||||
BSS = 0x1,
|
||||
OFDM_PREAMBLE = 0x2,
|
||||
UNIDENTIFIED_SIGNAL = 0x4,
|
||||
RADAR = 0x8,
|
||||
UNMEASURED = 0x10,
|
||||
RESERVED = 0xE0
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents the IEEE 802.11 frames' capability information.
|
||||
@@ -105,39 +132,39 @@ public:
|
||||
class capability_information {
|
||||
private:
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
uint16_t _ess:1,
|
||||
_ibss:1,
|
||||
_cf_poll:1,
|
||||
_cf_poll_req:1,
|
||||
_privacy:1,
|
||||
_short_preamble:1,
|
||||
_pbcc:1,
|
||||
_channel_agility:1,
|
||||
_spectrum_mgmt:1,
|
||||
_qos:1,
|
||||
_sst:1,
|
||||
_apsd:1,
|
||||
_reserved:1,
|
||||
_dsss_ofdm:1,
|
||||
_delayed_block_ack:1,
|
||||
_immediate_block_ack:1;
|
||||
uint16_t ess_:1,
|
||||
ibss_:1,
|
||||
cf_poll_:1,
|
||||
cf_poll_req_:1,
|
||||
privacy_:1,
|
||||
short_preamble_:1,
|
||||
pbcc_:1,
|
||||
channel_agility_:1,
|
||||
spectrum_mgmt_:1,
|
||||
qos_:1,
|
||||
sst_:1,
|
||||
apsd_:1,
|
||||
radio_measurement_:1,
|
||||
dsss_ofdm_:1,
|
||||
delayed_block_ack_:1,
|
||||
immediate_block_ack_:1;
|
||||
#elif TINS_IS_BIG_ENDIAN
|
||||
uint16_t _channel_agility:1,
|
||||
_pbcc:1,
|
||||
_short_preamble:1,
|
||||
_privacy:1,
|
||||
_cf_poll_req:1,
|
||||
_cf_poll:1,
|
||||
_ibss:1,
|
||||
_ess:1,
|
||||
_immediate_block_ack:1,
|
||||
_delayed_block_ack:1,
|
||||
_dsss_ofdm:1,
|
||||
_reserved:1,
|
||||
_apsd:1,
|
||||
_sst:1,
|
||||
_qos:1,
|
||||
_spectrum_mgmt:1;
|
||||
uint16_t channel_agility_:1,
|
||||
pbcc_:1,
|
||||
short_preamble_:1,
|
||||
privacy_:1,
|
||||
cf_poll_req_:1,
|
||||
cf_poll_:1,
|
||||
ibss_:1,
|
||||
ess_:1,
|
||||
immediate_block_ack_:1,
|
||||
delayed_block_ack_:1,
|
||||
dsss_ofdm_:1,
|
||||
radio_measurement_:1,
|
||||
apsd_:1,
|
||||
sst_:1,
|
||||
qos_:1,
|
||||
spectrum_mgmt_:1;
|
||||
#endif
|
||||
public:
|
||||
/**
|
||||
@@ -145,225 +172,288 @@ public:
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool ess() const { return _ess; }
|
||||
bool ess() const {
|
||||
return ess_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the ibss flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool ibss() const { return _ibss; }
|
||||
bool ibss() const {
|
||||
return ibss_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the cf_poll flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool cf_poll() const { return _cf_poll; }
|
||||
bool cf_poll() const {
|
||||
return cf_poll_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the cf_poll_req flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool cf_poll_req() const { return _cf_poll_req; }
|
||||
bool cf_poll_req() const {
|
||||
return cf_poll_req_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the privacy flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool privacy() const { return _privacy; }
|
||||
bool privacy() const {
|
||||
return privacy_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the short_preamble flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool short_preamble() const { return _short_preamble; }
|
||||
bool short_preamble() const {
|
||||
return short_preamble_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the pbcc flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool pbcc() const { return _pbcc; }
|
||||
bool pbcc() const {
|
||||
return pbcc_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the channel_agility flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool channel_agility() const { return _channel_agility; }
|
||||
bool channel_agility() const {
|
||||
return channel_agility_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the spectrum_mgmt flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool spectrum_mgmt() const { return _spectrum_mgmt; }
|
||||
bool spectrum_mgmt() const {
|
||||
return spectrum_mgmt_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the qos flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool qos() const { return _qos; }
|
||||
bool qos() const {
|
||||
return qos_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the sst flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool sst() const { return _sst; }
|
||||
bool sst() const {
|
||||
return sst_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the apsd flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool apsd() const { return _apsd; }
|
||||
bool apsd() const {
|
||||
return apsd_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the reserved flag.
|
||||
* \brief Getter for the radio measurement flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool reserved() const { return _reserved; }
|
||||
bool radio_measurement() const {
|
||||
return radio_measurement_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the dsss_ofdm flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool dsss_ofdm() const { return _dsss_ofdm; }
|
||||
bool dsss_ofdm() const {
|
||||
return dsss_ofdm_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the delayed_block_ack flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool delayed_block_ack() const { return _delayed_block_ack; }
|
||||
bool delayed_block_ack() const {
|
||||
return delayed_block_ack_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the immediate_block_ack flag.
|
||||
*
|
||||
* \return Bool indicating the flag's value.
|
||||
*/
|
||||
bool immediate_block_ack() const { return _immediate_block_ack; }
|
||||
bool immediate_block_ack() const {
|
||||
return immediate_block_ack_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the ess flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void ess(bool new_value) { _ess = new_value; }
|
||||
void ess(bool new_value) {
|
||||
ess_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the ibss flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void ibss(bool new_value) { _ibss = new_value; }
|
||||
void ibss(bool new_value) {
|
||||
ibss_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the cf_poll flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void cf_poll(bool new_value) { _cf_poll = new_value; }
|
||||
void cf_poll(bool new_value) {
|
||||
cf_poll_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the cf_poll_req flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void cf_poll_req(bool new_value) { _cf_poll_req = new_value; }
|
||||
void cf_poll_req(bool new_value) {
|
||||
cf_poll_req_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the privacy flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void privacy(bool new_value) { _privacy = new_value; }
|
||||
void privacy(bool new_value) {
|
||||
privacy_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the short_preamble flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void short_preamble(bool new_value) { _short_preamble = new_value; }
|
||||
void short_preamble(bool new_value) {
|
||||
short_preamble_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the pbcc flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void pbcc(bool new_value) { _pbcc = new_value; }
|
||||
void pbcc(bool new_value) {
|
||||
pbcc_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the channel_agility flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void channel_agility(bool new_value) { _channel_agility = new_value; }
|
||||
void channel_agility(bool new_value) {
|
||||
channel_agility_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the spectrum_mgmt flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void spectrum_mgmt(bool new_value) { _spectrum_mgmt = new_value; }
|
||||
void spectrum_mgmt(bool new_value) {
|
||||
spectrum_mgmt_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the qos flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void qos(bool new_value) { _qos = new_value; }
|
||||
void qos(bool new_value) {
|
||||
qos_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the sst flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void sst(bool new_value) { _sst = new_value; }
|
||||
void sst(bool new_value) {
|
||||
sst_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the apsd flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void apsd(bool new_value) { _apsd = new_value; }
|
||||
void apsd(bool new_value) {
|
||||
apsd_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the reserved flag.
|
||||
* \brief Setter for the radio measurement flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void reserved(bool new_value) { _reserved = new_value; }
|
||||
void radio_measurement(bool new_value) {
|
||||
radio_measurement_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the dsss_ofdm flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void dsss_ofdm(bool new_value) { _dsss_ofdm = new_value; }
|
||||
void dsss_ofdm(bool new_value) {
|
||||
dsss_ofdm_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the delayed_block_ack flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void delayed_block_ack(bool new_value) { _delayed_block_ack = new_value; }
|
||||
void delayed_block_ack(bool new_value) {
|
||||
delayed_block_ack_ = new_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the immediate_block_ack flag.
|
||||
*
|
||||
* \param new_value bool indicating the flag's new value.
|
||||
*/
|
||||
void immediate_block_ack(bool new_value) { _immediate_block_ack = new_value; }
|
||||
|
||||
void immediate_block_ack(bool new_value) {
|
||||
immediate_block_ack_ = new_value;
|
||||
}
|
||||
} TINS_END_PACK;
|
||||
|
||||
/**
|
||||
@@ -373,14 +463,17 @@ public:
|
||||
uint16_t dwell_time;
|
||||
uint8_t hop_set, hop_pattern, hop_index;
|
||||
|
||||
fh_params_set() {}
|
||||
fh_params_set()
|
||||
: dwell_time(0), hop_set(0), hop_pattern(0), hop_index(0) {}
|
||||
|
||||
fh_params_set(uint16_t dwell_time, uint8_t hop_set,
|
||||
uint8_t hop_pattern, uint8_t hop_index)
|
||||
fh_params_set(uint16_t dwell_time,
|
||||
uint8_t hop_set,
|
||||
uint8_t hop_pattern,
|
||||
uint8_t hop_index)
|
||||
: dwell_time(dwell_time), hop_set(hop_set),
|
||||
hop_pattern(hop_pattern), hop_index(hop_index) {}
|
||||
|
||||
static fh_params_set from_option(const option &opt);
|
||||
static fh_params_set from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -390,15 +483,18 @@ public:
|
||||
uint8_t cfp_count, cfp_period;
|
||||
uint16_t cfp_max_duration, cfp_dur_remaining;
|
||||
|
||||
cf_params_set() {}
|
||||
cf_params_set()
|
||||
: cfp_count(0), cfp_period(0), cfp_max_duration(0), cfp_dur_remaining(0) {}
|
||||
|
||||
cf_params_set(uint8_t cfp_count, uint8_t cfp_period,
|
||||
uint16_t cfp_max_duration, uint16_t cfp_dur_remaining)
|
||||
cf_params_set(uint8_t cfp_count,
|
||||
uint8_t cfp_period,
|
||||
uint16_t cfp_max_duration,
|
||||
uint16_t cfp_dur_remaining)
|
||||
: cfp_count(cfp_count), cfp_period(cfp_period),
|
||||
cfp_max_duration(cfp_max_duration),
|
||||
cfp_dur_remaining(cfp_dur_remaining) {}
|
||||
|
||||
static cf_params_set from_option(const option &opt);
|
||||
static cf_params_set from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -409,16 +505,17 @@ public:
|
||||
|
||||
address_type dfs_owner;
|
||||
uint8_t recovery_interval;
|
||||
channels_type channel_map;
|
||||
channel_map_type channel_map;
|
||||
|
||||
ibss_dfs_params() {}
|
||||
ibss_dfs_params() : recovery_interval(0) {}
|
||||
|
||||
ibss_dfs_params(const address_type &addr,
|
||||
uint8_t recovery_interval, const channels_type &channels)
|
||||
ibss_dfs_params(const address_type& addr,
|
||||
uint8_t recovery_interval,
|
||||
const channel_map_type& channel_map)
|
||||
: dfs_owner(addr), recovery_interval(recovery_interval),
|
||||
channel_map(channels) {}
|
||||
channel_map(channel_map) {}
|
||||
|
||||
static ibss_dfs_params from_option(const option &opt);
|
||||
static ibss_dfs_params from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -433,12 +530,14 @@ public:
|
||||
|
||||
country_params() {}
|
||||
|
||||
country_params(const std::string &country, const byte_array &first,
|
||||
const byte_array &number, const byte_array &max)
|
||||
country_params(const std::string& country,
|
||||
const byte_array& first,
|
||||
const byte_array& number,
|
||||
const byte_array& max)
|
||||
: country(country), first_channel(first), number_channels(number),
|
||||
max_transmit_power(max) {}
|
||||
|
||||
static country_params from_option(const option &opt);
|
||||
static country_params from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -450,14 +549,18 @@ public:
|
||||
uint8_t flag, number_of_sets, modulus, offset;
|
||||
byte_array random_table;
|
||||
|
||||
fh_pattern_type() {}
|
||||
fh_pattern_type()
|
||||
: flag(0), number_of_sets(0), modulus(0), offset(0) {}
|
||||
|
||||
fh_pattern_type(uint8_t flag, uint8_t sets, uint8_t modulus,
|
||||
uint8_t offset, const byte_array& table)
|
||||
fh_pattern_type(uint8_t flag,
|
||||
uint8_t sets,
|
||||
uint8_t modulus,
|
||||
uint8_t offset,
|
||||
const byte_array& table)
|
||||
: flag(flag), number_of_sets(sets), modulus(modulus),
|
||||
offset(offset), random_table(table) {}
|
||||
|
||||
static fh_pattern_type from_option(const option &opt);
|
||||
static fh_pattern_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -466,12 +569,15 @@ public:
|
||||
struct channel_switch_type {
|
||||
uint8_t switch_mode, new_channel, switch_count;
|
||||
|
||||
channel_switch_type() {}
|
||||
channel_switch_type()
|
||||
: switch_mode(0), new_channel(0), switch_count(0) {}
|
||||
|
||||
channel_switch_type(uint8_t mode, uint8_t channel, uint8_t count)
|
||||
channel_switch_type(uint8_t mode,
|
||||
uint8_t channel,
|
||||
uint8_t count)
|
||||
: switch_mode(mode), new_channel(channel), switch_count(count) { }
|
||||
|
||||
static channel_switch_type from_option(const option &opt);
|
||||
static channel_switch_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -481,14 +587,17 @@ public:
|
||||
uint8_t quiet_count, quiet_period;
|
||||
uint16_t quiet_duration, quiet_offset;
|
||||
|
||||
quiet_type() {}
|
||||
quiet_type()
|
||||
: quiet_count(0), quiet_period(0), quiet_duration(0), quiet_offset(0) {}
|
||||
|
||||
quiet_type(uint8_t count, uint8_t period, uint16_t duration,
|
||||
uint16_t offset)
|
||||
quiet_type(uint8_t count,
|
||||
uint8_t period,
|
||||
uint16_t duration,
|
||||
uint16_t offset)
|
||||
: quiet_count(count), quiet_period(period),
|
||||
quiet_duration(duration), quiet_offset(offset) {}
|
||||
|
||||
static quiet_type from_option(const option &opt);
|
||||
static quiet_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -499,14 +608,14 @@ public:
|
||||
uint16_t available_capacity;
|
||||
uint8_t channel_utilization;
|
||||
|
||||
bss_load_type() {}
|
||||
bss_load_type()
|
||||
: station_count(0), available_capacity(0), channel_utilization(0) {}
|
||||
|
||||
bss_load_type(uint16_t count, uint8_t utilization,
|
||||
uint16_t capacity)
|
||||
bss_load_type(uint16_t count, uint8_t utilization, uint16_t capacity)
|
||||
: station_count(count), available_capacity(capacity),
|
||||
channel_utilization(utilization) {}
|
||||
|
||||
static bss_load_type from_option(const option &opt);
|
||||
static bss_load_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -516,14 +625,17 @@ public:
|
||||
uint8_t dtim_count, dtim_period, bitmap_control;
|
||||
byte_array partial_virtual_bitmap;
|
||||
|
||||
tim_type() {}
|
||||
tim_type()
|
||||
: dtim_count(0), dtim_period(0), bitmap_control(0) {}
|
||||
|
||||
tim_type(uint8_t count, uint8_t period, uint8_t control,
|
||||
const byte_array &bitmap)
|
||||
tim_type(uint8_t count,
|
||||
uint8_t period,
|
||||
uint8_t control,
|
||||
const byte_array& bitmap)
|
||||
: dtim_count(count), dtim_period(period), bitmap_control(control),
|
||||
partial_virtual_bitmap(bitmap) {}
|
||||
|
||||
static tim_type from_option(const option &opt);
|
||||
static tim_type from_option(const option& opt);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -535,11 +647,11 @@ public:
|
||||
oui_type oui;
|
||||
byte_array data;
|
||||
|
||||
vendor_specific_type(const oui_type &oui = oui_type(),
|
||||
const byte_array &data = byte_array())
|
||||
vendor_specific_type(const oui_type& oui = oui_type(),
|
||||
const byte_array& data = byte_array())
|
||||
: oui(oui), data(data) { }
|
||||
|
||||
static vendor_specific_type from_bytes(const uint8_t *buffer, uint32_t sz);
|
||||
static vendor_specific_type from_bytes(const uint8_t* buffer, uint32_t sz);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -552,14 +664,18 @@ public:
|
||||
*
|
||||
* \return address_type containing the second address.
|
||||
*/
|
||||
address_type addr2() const { return _ext_header.addr2; }
|
||||
address_type addr2() const {
|
||||
return ext_header_.addr2;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the third address.
|
||||
*
|
||||
* \return address_type containing the third address.
|
||||
*/
|
||||
address_type addr3() const { return _ext_header.addr3; }
|
||||
address_type addr3() const {
|
||||
return ext_header_.addr3;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the fragment number.
|
||||
@@ -568,9 +684,9 @@ public:
|
||||
*/
|
||||
small_uint<4> frag_num() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return _ext_header.frag_seq & 0xf;
|
||||
return ext_header_.frag_seq & 0xf;
|
||||
#else
|
||||
return (_ext_header.frag_seq >> 8) & 0xf;
|
||||
return (ext_header_.frag_seq >> 8) & 0xf;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -581,9 +697,9 @@ public:
|
||||
*/
|
||||
small_uint<12> seq_num() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return (_ext_header.frag_seq >> 4) & 0xfff;
|
||||
return (ext_header_.frag_seq >> 4) & 0xfff;
|
||||
#else
|
||||
return (Endian::le_to_host<uint16_t>(_ext_header.frag_seq) >> 4) & 0xfff;
|
||||
return (Endian::le_to_host<uint16_t>(ext_header_.frag_seq) >> 4) & 0xfff;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -592,21 +708,23 @@ public:
|
||||
*
|
||||
* \return The stored fourth address.
|
||||
*/
|
||||
const address_type &addr4() const { return _addr4; }
|
||||
const address_type& addr4() const {
|
||||
return addr4_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the second address.
|
||||
*
|
||||
* \param new_addr2 The new second address to be set.
|
||||
*/
|
||||
void addr2(const address_type &new_addr2);
|
||||
void addr2(const address_type& new_addr2);
|
||||
|
||||
/**
|
||||
* \brief Setter for the third address.
|
||||
*
|
||||
* \param new_addr3 The new third address to be set.
|
||||
*/
|
||||
void addr3(const address_type &new_addr3);
|
||||
void addr3(const address_type& new_addr3);
|
||||
|
||||
/**
|
||||
* \brief Setter for the fragment number.
|
||||
@@ -627,7 +745,7 @@ public:
|
||||
*
|
||||
* \param new_addr4 The new fourth address to be set.
|
||||
*/
|
||||
void addr4(const address_type &new_addr4);
|
||||
void addr4(const address_type& new_addr4);
|
||||
|
||||
// Option setter helpers
|
||||
|
||||
@@ -636,7 +754,7 @@ public:
|
||||
*
|
||||
* \param new_ssid The SSID to be set.
|
||||
*/
|
||||
void ssid(const std::string &new_ssid);
|
||||
void ssid(const std::string& new_ssid);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the RSN information option.
|
||||
@@ -650,14 +768,14 @@ public:
|
||||
*
|
||||
* \param new_rates The new rates to be set.
|
||||
*/
|
||||
void supported_rates(const rates_type &new_rates);
|
||||
void supported_rates(const rates_type& new_rates);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the extended supported rates option.
|
||||
*
|
||||
* \param new_rates The new rates to be set.
|
||||
*/
|
||||
void extended_supported_rates(const rates_type &new_rates);
|
||||
void extended_supported_rates(const rates_type& new_rates);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the QoS capabilities option.
|
||||
@@ -683,7 +801,7 @@ public:
|
||||
*
|
||||
* \param new_channels A list of channels to be set.
|
||||
*/
|
||||
void supported_channels(const channels_type &new_channels);
|
||||
void supported_channels(const channels_type& new_channels);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the EDCA Parameter Set.
|
||||
@@ -707,7 +825,7 @@ public:
|
||||
*
|
||||
* \param fh_params The new FH parameter set value.
|
||||
*/
|
||||
void fh_parameter_set(const fh_params_set &fh_params);
|
||||
void fh_parameter_set(const fh_params_set& fh_params);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the DS parameter tagged option.
|
||||
@@ -721,7 +839,7 @@ public:
|
||||
*
|
||||
* \param params The new CF parameter set value.
|
||||
*/
|
||||
void cf_parameter_set(const cf_params_set ¶ms);
|
||||
void cf_parameter_set(const cf_params_set& params);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the IBSS parameter set tagged option.
|
||||
@@ -735,14 +853,14 @@ public:
|
||||
*
|
||||
* \param params The IBSS DFS data to be set.
|
||||
*/
|
||||
void ibss_dfs(const ibss_dfs_params ¶ms);
|
||||
void ibss_dfs(const ibss_dfs_params& params);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the country tagged option.
|
||||
*
|
||||
* \param params The data to be used for this country option.
|
||||
*/
|
||||
void country(const country_params ¶ms);
|
||||
void country(const country_params& params);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the FH parameters set tagged option.
|
||||
@@ -757,7 +875,7 @@ public:
|
||||
*
|
||||
* \param params The data to be used for this FH pattern table option.
|
||||
*/
|
||||
void fh_pattern_table(const fh_pattern_type ¶ms);
|
||||
void fh_pattern_table(const fh_pattern_type& params);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the Power Constraint tagged option.
|
||||
@@ -771,14 +889,14 @@ public:
|
||||
*
|
||||
* \param data The value of the Channel Switch option.
|
||||
*/
|
||||
void channel_switch(const channel_switch_type &data);
|
||||
void channel_switch(const channel_switch_type& data);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the Quiet tagged option.
|
||||
*
|
||||
* \param data The value of the quiet count field.
|
||||
*/
|
||||
void quiet(const quiet_type &data);
|
||||
void quiet(const quiet_type& data);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the TPC Report tagged option.
|
||||
@@ -800,28 +918,28 @@ public:
|
||||
*
|
||||
* \param data The value to set in this bss load option.
|
||||
*/
|
||||
void bss_load(const bss_load_type &data);
|
||||
void bss_load(const bss_load_type& data);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the TIM tagged option.
|
||||
*
|
||||
* \brief data The value to set in this tim option.
|
||||
*/
|
||||
void tim(const tim_type &data);
|
||||
void tim(const tim_type& data);
|
||||
|
||||
/**
|
||||
* \brief Helper method to set the Challenge Text tagged option.
|
||||
*
|
||||
* \brief text The challenge text to be added.
|
||||
*/
|
||||
void challenge_text(const std::string &text);
|
||||
void challenge_text(const std::string& text);
|
||||
|
||||
/**
|
||||
* \brief Helper method to add a Vendor Specific tagged option.
|
||||
*
|
||||
* \brief text The option to be added.
|
||||
*/
|
||||
void vendor_specific(const vendor_specific_type &data);
|
||||
void vendor_specific(const vendor_specific_type& data);
|
||||
|
||||
// Option searching helpers
|
||||
|
||||
@@ -834,7 +952,7 @@ public:
|
||||
*
|
||||
* \return std::string containing the ssid.
|
||||
*/
|
||||
RSNInformation rsn_information();
|
||||
RSNInformation rsn_information() const;
|
||||
|
||||
/**
|
||||
* \brief Helper method to search for this PDU's SSID.
|
||||
@@ -1096,10 +1214,12 @@ public:
|
||||
*
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -1108,15 +1228,15 @@ public:
|
||||
}
|
||||
protected:
|
||||
TINS_BEGIN_PACK
|
||||
struct ExtendedHeader {
|
||||
struct dot11_extended_header {
|
||||
uint8_t addr2[address_type::address_size];
|
||||
uint8_t addr3[address_type::address_size];
|
||||
uint16_t frag_seq;
|
||||
} TINS_END_PACK;
|
||||
|
||||
|
||||
Dot11ManagementFrame(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
Dot11ManagementFrame(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11ManagementFrame object from a buffer
|
||||
@@ -1132,29 +1252,30 @@ protected:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11ManagementFrame(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11ManagementFrame(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz);
|
||||
void write_ext_header(Memory::OutputMemoryStream& stream);
|
||||
|
||||
uint32_t management_frame_size() {
|
||||
return sizeof(ieee80211_header) + sizeof(_ext_header) +
|
||||
((from_ds() && to_ds()) ? address_type::address_size : 0);
|
||||
return Dot11ManagementFrame::header_size();
|
||||
}
|
||||
private:
|
||||
static uint8_t *serialize_rates(const rates_type &rates);
|
||||
static rates_type deserialize_rates(const option *option);
|
||||
static std::vector<uint8_t> serialize_rates(const rates_type& rates);
|
||||
static rates_type deserialize_rates(const option* option);
|
||||
|
||||
template<typename T>
|
||||
T search_and_convert(OptionTypes opt_type) const {
|
||||
const option *opt = search_option(opt_type);
|
||||
if(!opt)
|
||||
const option* opt = search_option(opt_type);
|
||||
if (!opt) {
|
||||
throw option_not_found();
|
||||
}
|
||||
return opt->to<T>();
|
||||
}
|
||||
|
||||
ExtendedHeader _ext_header;
|
||||
address_type _addr4;
|
||||
dot11_extended_header ext_header_;
|
||||
address_type addr4_;
|
||||
};
|
||||
|
||||
} // namespace Tins
|
||||
|
||||
#endif // TINS_DOT11_DOT11_MGMT_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -27,20 +27,21 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../config.h"
|
||||
#include <tins/config.h>
|
||||
|
||||
#if !defined(TINS_DOT11_DOT11_PROBE_H) && defined(HAVE_DOT11)
|
||||
#if !defined(TINS_DOT11_DOT11_PROBE_H) && defined(TINS_HAVE_DOT11)
|
||||
|
||||
#define TINS_DOT11_DOT11_PROBE_H
|
||||
|
||||
#include "../dot11/dot11_mgmt.h"
|
||||
#include <tins/dot11/dot11_mgmt.h>
|
||||
#include <tins/macros.h>
|
||||
|
||||
namespace Tins {
|
||||
/**
|
||||
* \brief Class representing an Probe Request frame in the IEEE 802.11 Protocol.
|
||||
*
|
||||
*/
|
||||
class Dot11ProbeRequest : public Dot11ManagementFrame {
|
||||
class TINS_API Dot11ProbeRequest : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -56,8 +57,8 @@ public:
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11ProbeRequest(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
Dot11ProbeRequest(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11ProbeRequest object from a buffer
|
||||
@@ -73,16 +74,18 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11ProbeRequest(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11ProbeRequest(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::DOT11_PROBE_REQ; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
@@ -105,7 +108,7 @@ public:
|
||||
* \brief Class representing an Probe Response frame in the IEEE 802.11 Protocol.
|
||||
*
|
||||
*/
|
||||
class Dot11ProbeResponse : public Dot11ManagementFrame {
|
||||
class TINS_API Dot11ProbeResponse : public Dot11ManagementFrame {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
@@ -121,8 +124,8 @@ public:
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
*/
|
||||
Dot11ProbeResponse(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
Dot11ProbeResponse(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot11ProbeResponse object from a buffer
|
||||
@@ -138,21 +141,25 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot11ProbeResponse(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot11ProbeResponse(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the timestamp field.
|
||||
*
|
||||
* \return The stored timestamp value.
|
||||
*/
|
||||
uint64_t timestamp() const { return Endian::le_to_host(_body.timestamp); }
|
||||
uint64_t timestamp() const {
|
||||
return Endian::le_to_host(body_.timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the interval field.
|
||||
*
|
||||
* \return The stored interval value.
|
||||
*/
|
||||
uint16_t interval() const { return Endian::le_to_host(_body.interval); }
|
||||
uint16_t interval() const {
|
||||
return Endian::le_to_host(body_.interval);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
@@ -160,7 +167,9 @@ public:
|
||||
* \return A constant reference to the stored Capabilities
|
||||
* Information field.
|
||||
*/
|
||||
const capability_information& capabilities() const { return _body.capability;}
|
||||
const capability_information& capabilities() const {
|
||||
return body_.capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the Capabilities Information.
|
||||
@@ -168,7 +177,9 @@ public:
|
||||
* \return A reference to the stored Capabilities Information
|
||||
* field.
|
||||
*/
|
||||
capability_information& capabilities() { return _body.capability;}
|
||||
capability_information& capabilities() {
|
||||
return body_.capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the timestamp field.
|
||||
@@ -208,26 +219,26 @@ public:
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \brief Check wether this PDU matches the specified flag.
|
||||
* \brief Check whether this PDU matches the specified flag.
|
||||
* \param flag The flag to match
|
||||
* \sa PDU::matches_flag
|
||||
*/
|
||||
bool matches_flag(PDUType flag) const {
|
||||
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
|
||||
return flag == pdu_flag || Dot11ManagementFrame::matches_flag(flag);
|
||||
}
|
||||
protected:
|
||||
|
||||
private:
|
||||
void write_fixed_parameters(Memory::OutputMemoryStream& stream);
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct ProbeResp {
|
||||
struct dot11_probe_response_header {
|
||||
uint64_t timestamp;
|
||||
uint16_t interval;
|
||||
capability_information capability;
|
||||
} TINS_END_PACK;
|
||||
|
||||
ProbeResp _body;
|
||||
|
||||
uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz);
|
||||
dot11_probe_response_header body_;
|
||||
};
|
||||
|
||||
} // namespace Tins
|
||||
|
||||
#endif // TINS_DOT11_DOT11_PROBE_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -30,22 +30,32 @@
|
||||
#ifndef TINS_DOT1Q_H
|
||||
#define TINS_DOT1Q_H
|
||||
|
||||
#include "pdu.h"
|
||||
#include "endianness.h"
|
||||
#include "small_uint.h"
|
||||
#include <tins/pdu.h>
|
||||
#include <tins/macros.h>
|
||||
#include <tins/endianness.h>
|
||||
#include <tins/small_uint.h>
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class Dot1Q
|
||||
* Represents an IEEE 802.1q PDU.
|
||||
*/
|
||||
class Dot1Q : public PDU {
|
||||
class TINS_API Dot1Q : public PDU {
|
||||
public:
|
||||
/**
|
||||
* This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::DOT1Q;
|
||||
|
||||
/**
|
||||
* \brief Extracts metadata for this protocol based on the buffer provided
|
||||
*
|
||||
* \param buffer Pointer to a buffer
|
||||
* \param total_sz Size of the buffer pointed by buffer
|
||||
*/
|
||||
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
@@ -64,14 +74,14 @@ public:
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot1Q(const uint8_t *buffer, uint32_t total_sz);
|
||||
Dot1Q(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
// Getters
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
* This metod overrides PDU::header_size. \sa PDU::header_size
|
||||
* This method overrides PDU::header_size. \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
@@ -86,7 +96,7 @@ public:
|
||||
* \return The stored priority field value.
|
||||
*/
|
||||
small_uint<3> priority() const {
|
||||
return _header.priority;
|
||||
return header_.priority;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,7 +104,7 @@ public:
|
||||
* \return The stored CFI field value.
|
||||
*/
|
||||
small_uint<1> cfi() const {
|
||||
return _header.cfi;
|
||||
return header_.cfi;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,9 +113,9 @@ public:
|
||||
*/
|
||||
small_uint<12> id() const {
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
return _header.idL | (_header.idH << 8);
|
||||
return header_.idL | (header_.idH << 8);
|
||||
#else
|
||||
return _header.id;
|
||||
return header_.id;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -114,19 +124,21 @@ public:
|
||||
* \return The stored type field value.
|
||||
*/
|
||||
uint16_t payload_type() const {
|
||||
return Endian::be_to_host(_header.type);
|
||||
return Endian::be_to_host(header_.type);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot1Q *clone() const {
|
||||
Dot1Q* clone() const {
|
||||
return new Dot1Q(*this);
|
||||
}
|
||||
|
||||
@@ -135,7 +147,7 @@ public:
|
||||
* appended at the end of this packet.
|
||||
*/
|
||||
bool append_padding() const {
|
||||
return _append_padding;
|
||||
return append_padding_;
|
||||
}
|
||||
|
||||
// Setters
|
||||
@@ -177,18 +189,18 @@ public:
|
||||
void append_padding(bool value);
|
||||
|
||||
/**
|
||||
* \brief Check wether ptr points to a valid response for this PDU.
|
||||
* \brief Check whether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
|
||||
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
|
||||
private:
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
TINS_BEGIN_PACK
|
||||
struct dot1q_hdr {
|
||||
struct dot1q_header {
|
||||
#if TINS_IS_BIG_ENDIAN
|
||||
uint16_t priority:3,
|
||||
cfi:1,
|
||||
@@ -203,10 +215,10 @@ private:
|
||||
#endif
|
||||
} TINS_END_PACK;
|
||||
|
||||
static uint16_t get_id(const dot1q_hdr *hdr);
|
||||
static uint16_t get_id(const dot1q_header* hdr);
|
||||
|
||||
dot1q_hdr _header;
|
||||
bool _append_padding;
|
||||
dot1q_header header_;
|
||||
bool append_padding_;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -31,164 +31,179 @@
|
||||
#define TINS_DOT3_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "macros.h"
|
||||
#include "pdu.h"
|
||||
#include "endianness.h"
|
||||
#include "hw_address.h"
|
||||
#include <tins/macros.h>
|
||||
#include <tins/pdu.h>
|
||||
#include <tins/config.h>
|
||||
#include <tins/endianness.h>
|
||||
#include <tins/hw_address.h>
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class Dot3
|
||||
* \brief Class representing an IEEE 802.3 PDU.
|
||||
/**
|
||||
* \class Dot3
|
||||
* \brief Class representing an IEEE 802.3 PDU.
|
||||
*/
|
||||
class TINS_API Dot3 : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief The address type.
|
||||
*/
|
||||
class Dot3 : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief The address type.
|
||||
*/
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::IEEE802_3;
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::IEEE802_3;
|
||||
|
||||
/**
|
||||
* \brief Represents the Dot3 broadcast address.
|
||||
*/
|
||||
static const address_type BROADCAST;
|
||||
/**
|
||||
* \brief Represents the Dot3 broadcast address.
|
||||
*/
|
||||
static const address_type BROADCAST;
|
||||
|
||||
/**
|
||||
* \brief Constructor for creating an Dot3 PDU
|
||||
*
|
||||
* Constructor that builds an Dot3 PDU taking the interface name,
|
||||
* destination's and source's MAC.
|
||||
*
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
* \param child The PDU which will be set as the inner PDU.
|
||||
*/
|
||||
Dot3(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
/**
|
||||
* \brief Extracts metadata for this protocol based on the buffer provided
|
||||
*
|
||||
* \param buffer Pointer to a buffer
|
||||
* \param total_sz Size of the buffer pointed by buffer
|
||||
*/
|
||||
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Constructs a Dot3 object from a buffer and adds a
|
||||
* LLC object with the remaining data as the inner PDU.
|
||||
*
|
||||
* If there is not enough size for a Dot3 header, a
|
||||
* malformed_packet exception is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot3(const uint8_t *buffer, uint32_t total_sz);
|
||||
/**
|
||||
* \brief Constructor for creating an Dot3 PDU
|
||||
*
|
||||
* Constructor that builds an Dot3 PDU taking the interface name,
|
||||
* destination's and source's MAC.
|
||||
*
|
||||
* \param dst_hw_addr The destination hardware address.
|
||||
* \param src_hw_addr The source hardware address.
|
||||
* \param child The PDU which will be set as the inner PDU.
|
||||
*/
|
||||
Dot3(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/* Getters */
|
||||
/**
|
||||
* \brief Getter for the destination hardware address.
|
||||
*
|
||||
* \return The destination hardware address.
|
||||
*/
|
||||
address_type dst_addr() const { return _eth.dst_mac; }
|
||||
/**
|
||||
* \brief Constructs a Dot3 object from a buffer and adds a
|
||||
* LLC object with the remaining data as the inner PDU.
|
||||
*
|
||||
* If there is not enough size for a Dot3 header, a
|
||||
* malformed_packet exception is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
Dot3(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the source hardware address.
|
||||
*
|
||||
* \return The source hardware address.
|
||||
*/
|
||||
address_type src_addr() const { return _eth.src_mac; }
|
||||
/* Getters */
|
||||
/**
|
||||
* \brief Getter for the destination hardware address.
|
||||
*
|
||||
* \return The destination hardware address.
|
||||
*/
|
||||
address_type dst_addr() const {
|
||||
return header_.dst_mac;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the length field.
|
||||
* \return The length field value.
|
||||
*/
|
||||
uint16_t length() const { return Endian::be_to_host(_eth.length); };
|
||||
/**
|
||||
* \brief Getter for the source hardware address.
|
||||
*
|
||||
* \return The source hardware address.
|
||||
*/
|
||||
address_type src_addr() const {
|
||||
return header_.src_mac;
|
||||
}
|
||||
|
||||
/* Setters */
|
||||
/**
|
||||
* \brief Getter for the length field.
|
||||
* \return The length field value.
|
||||
*/
|
||||
uint16_t length() const {
|
||||
return Endian::be_to_host(header_.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the destination hardware address.
|
||||
*
|
||||
* \param new_dst_mac The new destination hardware address.
|
||||
*/
|
||||
void dst_addr(const address_type &new_dst_mac);
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the source hardware address.
|
||||
*
|
||||
* \param new_src_mac The new source hardware address.
|
||||
*/
|
||||
void src_addr(const address_type &new_src_mac);
|
||||
/**
|
||||
* \brief Setter for the destination hardware address.
|
||||
*
|
||||
* \param address The new destination hardware address.
|
||||
*/
|
||||
void dst_addr(const address_type& address);
|
||||
|
||||
/**
|
||||
* \brief Setter for the length field.
|
||||
*
|
||||
* \param new_length uint16_t with the new value of the length field.
|
||||
*/
|
||||
void length(uint16_t new_length);
|
||||
/**
|
||||
* \brief Setter for the source hardware address.
|
||||
*
|
||||
* \param address The new source hardware address.
|
||||
*/
|
||||
void src_addr(const address_type& address);
|
||||
|
||||
/* Virtual methods */
|
||||
/**
|
||||
* \brief Returns the Dot3 frame's header length.
|
||||
*
|
||||
* \return An uint32_t with the header's size.
|
||||
* \sa PDU::header_size()
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
#ifndef WIN32
|
||||
/**
|
||||
* \sa PDU::send()
|
||||
*/
|
||||
void send(PacketSender &sender, const NetworkInterface &iface);
|
||||
#endif // WIN32
|
||||
/**
|
||||
* \brief Setter for the length field.
|
||||
*
|
||||
* \param value The new value for the length field
|
||||
*/
|
||||
void length(uint16_t value);
|
||||
|
||||
/**
|
||||
* \brief Check wether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
|
||||
// Virtual methods
|
||||
|
||||
#ifndef WIN32
|
||||
/**
|
||||
* \sa PDU::recv_response
|
||||
*/
|
||||
PDU *recv_response(PacketSender &sender, const NetworkInterface &iface);
|
||||
#endif // WIN32
|
||||
/**
|
||||
* \brief Returns the Dot3 frame's header length.
|
||||
*
|
||||
* \return An uint32_t with the header's size.
|
||||
* \sa PDU::header_size()
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
#if !defined(_WIN32) || defined(TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET)
|
||||
/**
|
||||
* \sa PDU::send()
|
||||
*/
|
||||
void send(PacketSender& sender, const NetworkInterface& iface);
|
||||
#endif // !_WIN32 || TINS_HAVE_PACKET_SENDER_PCAP_SENDPACKET
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
/**
|
||||
* \brief Check whether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot3 *clone() const {
|
||||
return new Dot3(*this);
|
||||
}
|
||||
private:
|
||||
/**
|
||||
* Struct that represents the Ethernet II header
|
||||
*/
|
||||
TINS_BEGIN_PACK
|
||||
struct ethhdr {
|
||||
uint8_t dst_mac[address_type::address_size];
|
||||
uint8_t src_mac[address_type::address_size];
|
||||
uint16_t length;
|
||||
} TINS_END_PACK;
|
||||
#ifndef _WIN32
|
||||
/**
|
||||
* \sa PDU::recv_response
|
||||
*/
|
||||
PDU* recv_response(PacketSender& sender, const NetworkInterface& iface);
|
||||
#endif // _WIN32
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return pdu_flag; }
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
Dot3* clone() const {
|
||||
return new Dot3(*this);
|
||||
}
|
||||
private:
|
||||
/**
|
||||
* Struct that represents the Ethernet II header
|
||||
*/
|
||||
TINS_BEGIN_PACK
|
||||
struct dot3_header {
|
||||
uint8_t dst_mac[address_type::address_size];
|
||||
uint8_t src_mac[address_type::address_size];
|
||||
uint16_t length;
|
||||
} TINS_END_PACK;
|
||||
|
||||
ethhdr _eth;
|
||||
};
|
||||
}
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
dot3_header header_;
|
||||
};
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_DOT3_H
|
||||
|
||||
1435
include/tins/eapol.h
1435
include/tins/eapol.h
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -31,7 +31,7 @@
|
||||
#define TINS_ENDIANNESS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "macros.h"
|
||||
#include <tins/macros.h>
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <sys/types.h>
|
||||
@@ -41,7 +41,8 @@
|
||||
#include <sys/endian.h>
|
||||
#define TINS_IS_LITTLE_ENDIAN (_BYTE_ORDER == _LITTLE_ENDIAN)
|
||||
#define TINS_IS_BIG_ENDIAN (_BYTE_ORDER == _BIG_ENDIAN)
|
||||
#elif defined(WIN32)
|
||||
#elif defined(_WIN32)
|
||||
#include <cstdlib>
|
||||
// Assume windows == little endian. fixme later
|
||||
#define TINS_IS_LITTLE_ENDIAN 1
|
||||
#define TINS_IS_BIG_ENDIAN 0
|
||||
@@ -51,187 +52,208 @@
|
||||
#define TINS_IS_BIG_ENDIAN (__BYTE_ORDER == __BIG_ENDIAN)
|
||||
#endif
|
||||
|
||||
|
||||
// Define macros to swap bytes using compiler intrinsics when possible
|
||||
#if defined(_MSC_VER)
|
||||
#define TINS_BYTE_SWAP_16(data) _byteswap_ushort(data)
|
||||
#define TINS_BYTE_SWAP_32(data) _byteswap_ulong(data)
|
||||
#define TINS_BYTE_SWAP_64(data) _byteswap_uint64(data)
|
||||
#elif defined(TINS_HAVE_GCC_BUILTIN_SWAP)
|
||||
#define TINS_BYTE_SWAP_16(data) __builtin_bswap16(data)
|
||||
#define TINS_BYTE_SWAP_32(data) __builtin_bswap32(data)
|
||||
#define TINS_BYTE_SWAP_64(data) __builtin_bswap64(data)
|
||||
#else
|
||||
#define TINS_NO_BYTE_SWAP_INTRINSICS
|
||||
#endif
|
||||
|
||||
namespace Tins {
|
||||
namespace Endian {
|
||||
/**
|
||||
* \brief "Changes" a 8-bit integral value's endianess. This is an
|
||||
* identity function.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
inline uint8_t do_change_endian(uint8_t data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Changes a 16-bit integral value's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
inline uint16_t do_change_endian(uint16_t data) {
|
||||
|
||||
/**
|
||||
* \brief "Changes" a 8-bit integral value's endianess. This is an
|
||||
* identity function.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
inline uint8_t do_change_endian(uint8_t data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Changes a 16-bit integral value's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
inline uint16_t do_change_endian(uint16_t data) {
|
||||
#ifdef TINS_NO_BYTE_SWAP_INTRINSICS
|
||||
return ((data & 0xff00) >> 8) | ((data & 0x00ff) << 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Changes a 32-bit integral value's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
inline uint32_t do_change_endian(uint32_t data) {
|
||||
#else
|
||||
return TINS_BYTE_SWAP_16(data);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Changes a 32-bit integral value's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
inline uint32_t do_change_endian(uint32_t data) {
|
||||
#ifdef TINS_NO_BYTE_SWAP_INTRINSICS
|
||||
return (((data & 0xff000000) >> 24) | ((data & 0x00ff0000) >> 8) |
|
||||
((data & 0x0000ff00) << 8) | ((data & 0x000000ff) << 24));
|
||||
((data & 0x0000ff00) << 8) | ((data & 0x000000ff) << 24));
|
||||
#else
|
||||
return TINS_BYTE_SWAP_32(data);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Changes a 64-bit integral value's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
inline uint64_t do_change_endian(uint64_t data) {
|
||||
#ifdef TINS_NO_BYTE_SWAP_INTRINSICS
|
||||
return (((uint64_t)(do_change_endian((uint32_t)(data & 0xffffffff))) << 32) |
|
||||
(do_change_endian(((uint32_t)(data >> 32)))));
|
||||
#else
|
||||
return TINS_BYTE_SWAP_64(data);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \cond
|
||||
*/
|
||||
|
||||
// Helpers to convert
|
||||
template<typename T>
|
||||
struct conversion_dispatch_helper {
|
||||
static T dispatch(T data) {
|
||||
return do_change_endian(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Changes a 64-bit integral value's endianess.
|
||||
};
|
||||
|
||||
|
||||
template<size_t>
|
||||
struct conversion_dispatcher;
|
||||
|
||||
template<>
|
||||
struct conversion_dispatcher<sizeof(uint8_t)>
|
||||
: public conversion_dispatch_helper<uint8_t> { };
|
||||
|
||||
template<>
|
||||
struct conversion_dispatcher<sizeof(uint16_t)>
|
||||
: public conversion_dispatch_helper<uint16_t> { };
|
||||
|
||||
template<>
|
||||
struct conversion_dispatcher<sizeof(uint32_t)>
|
||||
: public conversion_dispatch_helper<uint32_t> { };
|
||||
|
||||
template<>
|
||||
struct conversion_dispatcher<sizeof(uint64_t)>
|
||||
: public conversion_dispatch_helper<uint64_t> { };
|
||||
|
||||
/**
|
||||
* \endcond
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Changes an integral value's endianess.
|
||||
*
|
||||
* This dispatchs to the corresponding function.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T change_endian(T data) {
|
||||
return conversion_dispatcher<sizeof(T)>::dispatch(data);
|
||||
}
|
||||
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
/**
|
||||
* \brief Convert any integral type to big endian.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
inline uint64_t do_change_endian(uint64_t data) {
|
||||
return (((uint64_t)(do_change_endian((uint32_t)(data & 0xffffffff))) << 32) |
|
||||
(do_change_endian(((uint32_t)(data >> 32)))));
|
||||
template<typename T>
|
||||
inline T host_to_be(T data) {
|
||||
return change_endian(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any integral type to little endian.
|
||||
*
|
||||
* On little endian platforms, the parameter is simply returned.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T host_to_le(T data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* \cond
|
||||
*/
|
||||
|
||||
// Helpers to convert
|
||||
template<typename T>
|
||||
struct conversion_dispatch_helper {
|
||||
static T dispatch(T data) {
|
||||
return do_change_endian(data);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<size_t>
|
||||
struct conversion_dispatcher;
|
||||
|
||||
template<>
|
||||
struct conversion_dispatcher<sizeof(uint8_t)>
|
||||
: public conversion_dispatch_helper<uint8_t>
|
||||
{ };
|
||||
|
||||
template<>
|
||||
struct conversion_dispatcher<sizeof(uint16_t)>
|
||||
: public conversion_dispatch_helper<uint16_t>
|
||||
{ };
|
||||
|
||||
template<>
|
||||
struct conversion_dispatcher<sizeof(uint32_t)>
|
||||
: public conversion_dispatch_helper<uint32_t>
|
||||
{ };
|
||||
|
||||
template<>
|
||||
struct conversion_dispatcher<sizeof(uint64_t)>
|
||||
: public conversion_dispatch_helper<uint64_t>
|
||||
{ };
|
||||
|
||||
/**
|
||||
* \endcond
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Changes an integral value's endianess.
|
||||
* \brief Convert any big endian value to the host's endianess.
|
||||
*
|
||||
* This dispatchs to the corresponding function.
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T be_to_host(T data) {
|
||||
return change_endian(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any little endian value to the host's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T le_to_host(T data) {
|
||||
return data;
|
||||
}
|
||||
#elif TINS_IS_BIG_ENDIAN
|
||||
/**
|
||||
* \brief Convert any integral type to big endian.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
*/
|
||||
template<typename T>
|
||||
inline T host_to_be(T data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any integral type to little endian.
|
||||
*
|
||||
* On little endian platforms, the parameter is simply returned.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T change_endian(T data) {
|
||||
return conversion_dispatcher<sizeof(T)>::dispatch(data);
|
||||
inline T host_to_le(T data) {
|
||||
return change_endian(data);
|
||||
}
|
||||
|
||||
#if TINS_IS_LITTLE_ENDIAN
|
||||
/**
|
||||
* \brief Convert any integral type to big endian.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T host_to_be(T data) {
|
||||
return change_endian(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any integral type to little endian.
|
||||
*
|
||||
* On little endian platforms, the parameter is simply returned.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T host_to_le(T data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any big endian value to the host's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T be_to_host(T data) {
|
||||
return change_endian(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any little endian value to the host's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T le_to_host(T data) {
|
||||
return data;
|
||||
}
|
||||
#elif TINS_IS_BIG_ENDIAN
|
||||
/**
|
||||
* \brief Convert any integral type to big endian.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T host_to_be(T data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any integral type to little endian.
|
||||
*
|
||||
* On little endian platforms, the parameter is simply returned.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T host_to_le(T data) {
|
||||
return change_endian(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any big endian value to the host's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T be_to_host(T data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any little endian value to the host's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T le_to_host(T data) {
|
||||
return change_endian(data);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any big endian value to the host's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T be_to_host(T data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert any little endian value to the host's endianess.
|
||||
*
|
||||
* \param data The data to convert.
|
||||
*/
|
||||
template<typename T>
|
||||
inline T le_to_host(T data) {
|
||||
return change_endian(data);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // Endian
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_ENDIANNESS_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -31,175 +31,188 @@
|
||||
#define TINS_ETHERNET_II_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "macros.h"
|
||||
#include "pdu.h"
|
||||
#include "endianness.h"
|
||||
#include "hw_address.h"
|
||||
#include <tins/macros.h>
|
||||
#include <tins/pdu.h>
|
||||
#include <tins/config.h>
|
||||
#include <tins/endianness.h>
|
||||
#include <tins/hw_address.h>
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \class EthernetII
|
||||
* \brief Represents an Ethernet II PDU.
|
||||
*/
|
||||
class TINS_API EthernetII : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \class EthernetII
|
||||
* \brief Represents an Ethernet II PDU.
|
||||
* \brief The hardware address type.
|
||||
*/
|
||||
class EthernetII : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief The hardware address type.
|
||||
*/
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::ETHERNET_II;
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::ETHERNET_II;
|
||||
|
||||
/**
|
||||
* \brief Represents the ethernetII broadcast address.
|
||||
*/
|
||||
static const address_type BROADCAST;
|
||||
/**
|
||||
* \brief Represents the ethernetII broadcast address.
|
||||
*/
|
||||
static const address_type BROADCAST;
|
||||
|
||||
/**
|
||||
* \brief Constructs an ethernet II PDU.
|
||||
*
|
||||
* \param dst_hw_addr address_type containing the destination's MAC.
|
||||
* \param src_hw_addr address_type containing the source's MAC.
|
||||
*/
|
||||
EthernetII(const address_type &dst_hw_addr = address_type(),
|
||||
const address_type &src_hw_addr = address_type());
|
||||
/**
|
||||
* \brief Extracts metadata for this protocol based on the buffer provided
|
||||
*
|
||||
* \param buffer Pointer to a buffer
|
||||
* \param total_sz Size of the buffer pointed by buffer
|
||||
*/
|
||||
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Constructs a EthernetII object from a buffer and adds
|
||||
* all identifiable PDUs found in the buffer as children of
|
||||
* this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for a EthernetII header in the
|
||||
* buffer, a malformed_packet exception is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
EthernetII(const uint8_t *buffer, uint32_t total_sz);
|
||||
/**
|
||||
* \brief Constructs an ethernet II PDU.
|
||||
*
|
||||
* \param dst_hw_addr address_type containing the destination's MAC.
|
||||
* \param src_hw_addr address_type containing the source's MAC.
|
||||
*/
|
||||
EthernetII(const address_type& dst_hw_addr = address_type(),
|
||||
const address_type& src_hw_addr = address_type());
|
||||
|
||||
/* Getters */
|
||||
/**
|
||||
* \brief Getter for the destination's hardware address.
|
||||
*
|
||||
* \return address_type containing the destination hardware
|
||||
* address.
|
||||
*/
|
||||
address_type dst_addr() const { return _eth.dst_mac; }
|
||||
/**
|
||||
* \brief Constructs a EthernetII object from a buffer and adds
|
||||
* all identifiable PDUs found in the buffer as children of
|
||||
* this one.
|
||||
*
|
||||
* If the next PDU is not recognized, then a RawPDU is used.
|
||||
*
|
||||
* If there is not enough size for a EthernetII header in the
|
||||
* buffer, a malformed_packet exception is thrown.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
EthernetII(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Getter for the source's hardware address.
|
||||
*
|
||||
* \return address_type containing the source hardware address.
|
||||
*/
|
||||
address_type src_addr() const { return _eth.src_mac; }
|
||||
/* Getters */
|
||||
/**
|
||||
* \brief Getter for the destination's hardware address.
|
||||
*
|
||||
* \return address_type containing the destination hardware
|
||||
* address.
|
||||
*/
|
||||
address_type dst_addr() const {
|
||||
return header_.dst_mac;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the payload_type
|
||||
* \return The payload type.
|
||||
*/
|
||||
uint16_t payload_type() const { return Endian::be_to_host(_eth.payload_type); };
|
||||
/**
|
||||
* \brief Getter for the source's hardware address.
|
||||
*
|
||||
* \return address_type containing the source hardware address.
|
||||
*/
|
||||
address_type src_addr() const {
|
||||
return header_.src_mac;
|
||||
}
|
||||
|
||||
/* Setters */
|
||||
/**
|
||||
* \brief Getter for the payload_type
|
||||
* \return The payload type.
|
||||
*/
|
||||
uint16_t payload_type() const {
|
||||
return Endian::be_to_host(header_.payload_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the destination hardware address.
|
||||
*
|
||||
* \param new_dst_addr the destination hardware address to be set.
|
||||
*/
|
||||
void dst_addr(const address_type &new_dst_addr);
|
||||
/* Setters */
|
||||
|
||||
/**
|
||||
* \brief Setter for the source hardware address.
|
||||
*
|
||||
* \param new_src_addr the source hardware address to be set.
|
||||
*/
|
||||
void src_addr(const address_type &new_src_addr);
|
||||
/**
|
||||
* \brief Setter for the destination hardware address.
|
||||
*
|
||||
* \param new_dst_addr the destination hardware address to be set.
|
||||
*/
|
||||
void dst_addr(const address_type& new_dst_addr);
|
||||
|
||||
/**
|
||||
* \brief Setter for the payload type.
|
||||
*
|
||||
* \param new_payload_type the new value of the payload type field.
|
||||
*/
|
||||
void payload_type(uint16_t new_payload_type);
|
||||
/**
|
||||
* \brief Setter for the source hardware address.
|
||||
*
|
||||
* \param new_src_addr the source hardware address to be set.
|
||||
*/
|
||||
void src_addr(const address_type& new_src_addr);
|
||||
|
||||
/* Virtual methods */
|
||||
/**
|
||||
* \brief Returns the ethernet frame's header length.
|
||||
*
|
||||
* \return An uint32_t with the header's size.
|
||||
* \sa PDU::header_size()
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Returns the ethernet II frame's padding.
|
||||
*
|
||||
* \return An uint32_t with the padding size.
|
||||
* \sa PDU::trailer_size()
|
||||
*/
|
||||
uint32_t trailer_size() const;
|
||||
/**
|
||||
* \brief Setter for the payload type.
|
||||
*
|
||||
* \param new_payload_type the new value of the payload type field.
|
||||
*/
|
||||
void payload_type(uint16_t new_payload_type);
|
||||
|
||||
// Windows does not support sending L2 PDUs.
|
||||
#ifndef WIN32
|
||||
/**
|
||||
* \sa PDU::send()
|
||||
*/
|
||||
void send(PacketSender &sender, const NetworkInterface &iface);
|
||||
#endif // WIN32
|
||||
/* Virtual methods */
|
||||
/**
|
||||
* \brief Returns the ethernet frame's header length.
|
||||
*
|
||||
* \return An uint32_t with the header's size.
|
||||
* \sa PDU::header_size()
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Returns the ethernet II frame's padding.
|
||||
*
|
||||
* \return An uint32_t with the padding size.
|
||||
* \sa PDU::trailer_size()
|
||||
*/
|
||||
uint32_t trailer_size() const;
|
||||
|
||||
/**
|
||||
* \brief Check wether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
|
||||
/**
|
||||
* \sa PDU::send()
|
||||
*/
|
||||
void send(PacketSender& sender, const NetworkInterface& iface);
|
||||
|
||||
#ifndef WIN32
|
||||
/**
|
||||
* \brief Receives a matching response for this packet.
|
||||
*
|
||||
* \sa PDU::recv_response
|
||||
*/
|
||||
PDU *recv_response(PacketSender &sender, const NetworkInterface &iface);
|
||||
#endif // WIN32
|
||||
/**
|
||||
* \brief Check whether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::ETHERNET_II; }
|
||||
#ifndef _WIN32
|
||||
/**
|
||||
* \brief Receives a matching response for this packet.
|
||||
*
|
||||
* \sa PDU::recv_response
|
||||
*/
|
||||
PDU* recv_response(PacketSender& sender, const NetworkInterface& iface);
|
||||
#endif // _WIN32
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
EthernetII *clone() const {
|
||||
return new EthernetII(*this);
|
||||
}
|
||||
private:
|
||||
/**
|
||||
* Struct that represents the Ethernet II header
|
||||
*/
|
||||
TINS_BEGIN_PACK
|
||||
struct ethhdr {
|
||||
uint8_t dst_mac[address_type::address_size];
|
||||
uint8_t src_mac[address_type::address_size];
|
||||
uint16_t payload_type;
|
||||
} TINS_END_PACK;
|
||||
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
ethhdr _eth;
|
||||
};
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
EthernetII* clone() const {
|
||||
return new EthernetII(*this);
|
||||
}
|
||||
private:
|
||||
/**
|
||||
* Struct that represents the Ethernet II header
|
||||
*/
|
||||
TINS_BEGIN_PACK
|
||||
struct ethernet_header {
|
||||
uint8_t dst_mac[address_type::address_size];
|
||||
uint8_t src_mac[address_type::address_size];
|
||||
uint16_t payload_type;
|
||||
} TINS_END_PACK;
|
||||
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
}
|
||||
ethernet_header header_;
|
||||
};
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_ETHERNET_II_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -34,152 +34,297 @@
|
||||
#include <stdexcept>
|
||||
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \brief Base class for all libtins exceptions.
|
||||
*/
|
||||
class exception_base : public std::runtime_error {
|
||||
public:
|
||||
exception_base()
|
||||
: std::runtime_error(std::string()) { }
|
||||
|
||||
exception_base(const std::string& message)
|
||||
: std::runtime_error(message) { }
|
||||
|
||||
exception_base(const char* message)
|
||||
: std::runtime_error(message) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when an option is not found.
|
||||
*/
|
||||
class option_not_found : public std::runtime_error {
|
||||
class option_not_found : public exception_base {
|
||||
public:
|
||||
option_not_found()
|
||||
: std::runtime_error(std::string()) { }
|
||||
|
||||
// try to avoid allocations by doing this.
|
||||
const char* what() const throw() {
|
||||
return "Option not found";
|
||||
}
|
||||
option_not_found() : exception_base("Option not found") { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when a malformed packet is parsed.
|
||||
*/
|
||||
class malformed_packet : public std::runtime_error {
|
||||
class malformed_packet : public exception_base {
|
||||
public:
|
||||
malformed_packet()
|
||||
: std::runtime_error(std::string()) { }
|
||||
malformed_packet() : exception_base("Malformed packet") { }
|
||||
malformed_packet(const std::string& message) : exception_base(message) { }
|
||||
};
|
||||
|
||||
const char* what() const throw() {
|
||||
return "Malformed packet";
|
||||
}
|
||||
/**
|
||||
* \brief Exception thrown when a DNS decompression pointer is out of bounds.
|
||||
*/
|
||||
class dns_decompression_pointer_out_of_bounds : public malformed_packet {
|
||||
public:
|
||||
dns_decompression_pointer_out_of_bounds() : malformed_packet("DNS decompression: pointer out of bounds") { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when a DNS decompression pointer loops.
|
||||
*/
|
||||
class dns_decompression_pointer_loops : public malformed_packet {
|
||||
public:
|
||||
dns_decompression_pointer_loops() : malformed_packet("DNS decompression: pointer loops") { }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when serializing a packet fails.
|
||||
*/
|
||||
class serialization_error : public exception_base {
|
||||
public:
|
||||
serialization_error() : exception_base("Serialization error") { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when a PDU is not found when using PDU::rfind_pdu.
|
||||
*/
|
||||
class pdu_not_found : public std::runtime_error {
|
||||
class pdu_not_found : public exception_base {
|
||||
public:
|
||||
pdu_not_found()
|
||||
: std::runtime_error(std::string()) { }
|
||||
|
||||
const char* what() const throw() {
|
||||
return "PDU not found";
|
||||
}
|
||||
pdu_not_found() : exception_base("PDU not found") { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when PDU::send requires a valid interface,
|
||||
* but an invalid is used.
|
||||
*/
|
||||
class invalid_interface : public std::runtime_error {
|
||||
class invalid_interface : public exception_base {
|
||||
public:
|
||||
invalid_interface()
|
||||
: std::runtime_error(std::string()) { }
|
||||
invalid_interface() : exception_base("Invalid interface") { }
|
||||
};
|
||||
|
||||
const char* what() const throw() {
|
||||
return "Invalid interface";
|
||||
}
|
||||
/**
|
||||
* \brief Exception thrown when an invalid string representation of an address
|
||||
* is provided
|
||||
*/
|
||||
class invalid_address : public exception_base {
|
||||
public:
|
||||
invalid_address() : exception_base("Invalid address") { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when a PDU option is set using an incorrect value
|
||||
*/
|
||||
class invalid_option_value : public exception_base {
|
||||
public:
|
||||
invalid_option_value() : exception_base("Invalid option value") { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when a field is not present in frame.
|
||||
*/
|
||||
class field_not_present : public std::runtime_error {
|
||||
class field_not_present : public exception_base {
|
||||
public:
|
||||
field_not_present()
|
||||
: std::runtime_error(std::string()) { }
|
||||
const char* what() const throw() {
|
||||
return "Field not present";
|
||||
}
|
||||
field_not_present() : exception_base("Field not present") { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when PacketSender fails to open a socket.
|
||||
*/
|
||||
class socket_open_error : public std::runtime_error {
|
||||
class socket_open_error : public exception_base {
|
||||
public:
|
||||
socket_open_error(const std::string &msg)
|
||||
: std::runtime_error(msg) { }
|
||||
socket_open_error(const std::string& msg)
|
||||
: exception_base(msg) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when PacketSender fails to close a socket.
|
||||
*/
|
||||
class socket_close_error : public std::runtime_error {
|
||||
class socket_close_error : public exception_base {
|
||||
public:
|
||||
socket_close_error(const std::string &msg)
|
||||
: std::runtime_error(msg) { }
|
||||
socket_close_error(const std::string& msg)
|
||||
: exception_base(msg) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when PacketSender fails to write on a socket.
|
||||
*/
|
||||
class socket_write_error : public std::runtime_error {
|
||||
class socket_write_error : public exception_base {
|
||||
public:
|
||||
socket_write_error(const std::string &msg)
|
||||
: std::runtime_error(msg) { }
|
||||
socket_write_error(const std::string& msg)
|
||||
: exception_base(msg) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when an invalid socket type is provided
|
||||
* to PacketSender.
|
||||
*/
|
||||
class invalid_socket_type : public std::exception {
|
||||
class invalid_socket_type : public exception_base {
|
||||
public:
|
||||
const char *what() const throw() {
|
||||
return "The provided socket type is invalid";
|
||||
}
|
||||
invalid_socket_type() : exception_base("The provided socket type is invalid") { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when an unkown link layer PDU type is
|
||||
* found while sniffing.
|
||||
*/
|
||||
class unknown_link_type : public std::exception {
|
||||
class unknown_link_type : public exception_base {
|
||||
public:
|
||||
const char *what() const throw() {
|
||||
return "The sniffed link layer PDU type is unknown";
|
||||
}
|
||||
unknown_link_type() : exception_base("The sniffed link layer PDU type is unknown") { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when a malformed option is found.
|
||||
*/
|
||||
class malformed_option : public std::exception {
|
||||
class malformed_option : public exception_base {
|
||||
public:
|
||||
const char *what() const throw() {
|
||||
return "Malformed option";
|
||||
}
|
||||
malformed_option() : exception_base("Malformed option") { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when a call to tins_cast fails.
|
||||
*/
|
||||
class bad_tins_cast : public std::exception {
|
||||
class bad_tins_cast : public exception_base {
|
||||
public:
|
||||
const char *what() const throw() {
|
||||
return "Bad Tins cast";
|
||||
}
|
||||
bad_tins_cast() : exception_base("Bad Tins cast") { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when sniffing a protocol that
|
||||
* has been disabled at compile time.
|
||||
*/
|
||||
class protocol_disabled : public std::exception {
|
||||
class protocol_disabled : public exception_base {
|
||||
public:
|
||||
const char *what() const throw() {
|
||||
return "Protocol disabled";
|
||||
protocol_disabled() : exception_base("Protocol disabled") { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when a feature has been disabled
|
||||
* at compile time.
|
||||
*/
|
||||
class feature_disabled : public exception_base {
|
||||
public:
|
||||
feature_disabled() : exception_base("Feature disabled") { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when a payload is too large to fit
|
||||
* into a PDUOption.
|
||||
*/
|
||||
class option_payload_too_large : public exception_base {
|
||||
public:
|
||||
option_payload_too_large() : exception_base("Option payload too large") { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when an IPv6 extension header is being
|
||||
* created from invalid data
|
||||
*/
|
||||
class invalid_ipv6_extension_header : public exception_base {
|
||||
public:
|
||||
invalid_ipv6_extension_header() : exception_base("Invalid IPv6 extension header") { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Generic pcap error
|
||||
*/
|
||||
class pcap_error : public exception_base {
|
||||
public:
|
||||
pcap_error(const char* message) : exception_base(message) {
|
||||
|
||||
}
|
||||
|
||||
pcap_error(const std::string& message) : exception_base(message) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when an invalid pcap filter is compiled
|
||||
*/
|
||||
class invalid_pcap_filter : public exception_base {
|
||||
public:
|
||||
invalid_pcap_filter(const char* message) : exception_base(message) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when serialiation of a non-serializable PDU
|
||||
* is attempted
|
||||
*/
|
||||
class pdu_not_serializable : public exception_base {
|
||||
public:
|
||||
pdu_not_serializable() : exception_base("PDU not serializable") { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when opening a pcap handle fails
|
||||
*/
|
||||
class pcap_open_failed : public exception_base {
|
||||
public:
|
||||
pcap_open_failed() : exception_base("Failed to create pcap handle") { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when a function not supported on the current OS
|
||||
* is called
|
||||
*/
|
||||
class unsupported_function : public exception_base {
|
||||
public:
|
||||
unsupported_function() : exception_base("Function is not supported on this OS") { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when an invalid domain name is parsed
|
||||
*/
|
||||
class invalid_domain_name : public exception_base {
|
||||
public:
|
||||
invalid_domain_name() : exception_base("Invalid domain name") { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when a stream is not found
|
||||
*/
|
||||
class stream_not_found : public exception_base {
|
||||
public:
|
||||
stream_not_found() : exception_base("Stream not found") { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when a required callback for an object is not set
|
||||
*/
|
||||
class callback_not_set : public exception_base {
|
||||
public:
|
||||
callback_not_set() : exception_base("Callback not set") { }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Exception thrown when an invalid packet is provided to some function
|
||||
*/
|
||||
class invalid_packet : public exception_base {
|
||||
public:
|
||||
invalid_packet() : exception_base("Invalid packet") { }
|
||||
};
|
||||
|
||||
namespace Crypto {
|
||||
namespace WPA2 {
|
||||
/**
|
||||
* \brief Exception thrown when an invalid WPA2 handshake is found.
|
||||
*/
|
||||
class invalid_handshake : public exception_base {
|
||||
public:
|
||||
invalid_handshake() : exception_base("Invalid WPA2 handshake") { }
|
||||
};
|
||||
} // WPA2
|
||||
} // Crypto
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_EXCEPTIONS_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -27,143 +27,144 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <tins/config.h>
|
||||
|
||||
#if !defined(TINS_HANDSHAKE_CAPTURER_H) && defined(HAVE_DOT11)
|
||||
#if !defined(TINS_HANDSHAKE_CAPTURER_H) && defined(TINS_HAVE_DOT11)
|
||||
#define TINS_HANDSHAKE_CAPTURER_H
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
#include "hw_address.h"
|
||||
#include "eapol.h"
|
||||
#include <tins/hw_address.h>
|
||||
#include <tins/macros.h>
|
||||
#include <tins/eapol.h>
|
||||
|
||||
// .h
|
||||
namespace Tins {
|
||||
|
||||
/**
|
||||
* \brief Generic EAPOL handshake.
|
||||
*
|
||||
* Stores both the client and supplicant addresses, as well as
|
||||
* all of the EAPOL packets used during the handshake.
|
||||
*/
|
||||
template<typename T>
|
||||
class EAPOLHandshake {
|
||||
public:
|
||||
typedef std::vector<T> container_type;
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
/**
|
||||
* \brief Generic EAPOL handshake.
|
||||
* \brief Default constructor.
|
||||
*/
|
||||
EAPOLHandshake() { }
|
||||
|
||||
/**
|
||||
* Constructs an EAPOLHandshake object.
|
||||
*
|
||||
* \param client_address The client address.
|
||||
* \param supplicant_address The supplicant address.
|
||||
* \param cont The container that holds the EAPOL packets used
|
||||
* in the handshake.
|
||||
*/
|
||||
EAPOLHandshake(const address_type& client_address,
|
||||
const address_type& supplicant_address,
|
||||
const container_type& cont)
|
||||
: cl_address_(client_address), suppl_address_(supplicant_address),
|
||||
handshake_(cont) {
|
||||
}
|
||||
|
||||
/**
|
||||
* \return const address_type&
|
||||
*/
|
||||
const address_type& client_address() const {
|
||||
return cl_address_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return const address_type&
|
||||
*/
|
||||
const address_type& supplicant_address() const {
|
||||
return suppl_address_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return const container_type&
|
||||
*/
|
||||
const container_type& handshake() const {
|
||||
return handshake_;
|
||||
}
|
||||
private:
|
||||
address_type cl_address_, suppl_address_;
|
||||
container_type handshake_;
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to store RSN handshakes.
|
||||
*/
|
||||
typedef EAPOLHandshake<RSNEAPOL> RSNHandshake;
|
||||
|
||||
/**
|
||||
* Captures 802.1X RSN handshakes.
|
||||
*/
|
||||
class TINS_API RSNHandshakeCapturer {
|
||||
public:
|
||||
/**
|
||||
* The type of handshakes that will be captured.
|
||||
*/
|
||||
typedef RSNHandshake handshake_type;
|
||||
|
||||
/**
|
||||
* The type in which all of the captured handshakes
|
||||
* will be stored.
|
||||
*/
|
||||
typedef std::vector<handshake_type> handshakes_type;
|
||||
|
||||
/**
|
||||
* \brief Processes a packet.
|
||||
*
|
||||
* This will fetch the RSNEAPOL layer, if any, and store
|
||||
* it in an intermediate storage. When a handshake is
|
||||
* completed, it will be stored separately.
|
||||
*
|
||||
* Stores both the client and supplicant addresses, as well as
|
||||
* all of the EAPOL packets used during the handshake.
|
||||
* \sa RSNHandshakeCapturer::handshakes
|
||||
*/
|
||||
template<typename T>
|
||||
class EAPOLHandshake {
|
||||
public:
|
||||
typedef std::vector<T> container_type;
|
||||
typedef HWAddress<6> address_type;
|
||||
|
||||
/**
|
||||
* \brief Default constructor.
|
||||
*/
|
||||
EAPOLHandshake() { }
|
||||
bool process_packet(const PDU& pdu);
|
||||
|
||||
/**
|
||||
* Constructs an EAPOLHandshake object.
|
||||
*
|
||||
* \param client_address The client address.
|
||||
* \param supplicant_address The supplicant address.
|
||||
* \param cont The container that holds the EAPOL packets used
|
||||
* in the handshake.
|
||||
*/
|
||||
EAPOLHandshake(const address_type &client_address,
|
||||
const address_type &supplicant_address, const container_type &cont)
|
||||
: cl_address_(client_address), suppl_address_(supplicant_address),
|
||||
handshake_(cont)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* \return const address_type&
|
||||
*/
|
||||
const address_type &client_address() const {
|
||||
return cl_address_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return const address_type&
|
||||
*/
|
||||
const address_type &supplicant_address() const {
|
||||
return suppl_address_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \return const container_type&
|
||||
*/
|
||||
const container_type &handshake() const {
|
||||
return handshake_;
|
||||
}
|
||||
private:
|
||||
address_type cl_address_, suppl_address_;
|
||||
container_type handshake_;
|
||||
};
|
||||
|
||||
/**
|
||||
* The type used to store RSN handshakes.
|
||||
* \brief Retrieves the completed handshakes.
|
||||
*
|
||||
* This will return the handshakes that have been completed
|
||||
* so far. A handshake is completed when the 4-way handshake
|
||||
* is captured.
|
||||
*
|
||||
* \sa RSNHandshakeCapturer::clear_handshakes
|
||||
*/
|
||||
typedef EAPOLHandshake<RSNEAPOL> RSNHandshake;
|
||||
|
||||
const handshakes_type& handshakes() const {
|
||||
return completed_handshakes_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures 802.1X RSN handshakes.
|
||||
* \brief Clears the completed handshakes.
|
||||
*
|
||||
* Since completed handshakes are stored in a std::vector,
|
||||
* it is advisable to remove all of them once they have been
|
||||
* processed.
|
||||
*/
|
||||
class RSNHandshakeCapturer {
|
||||
public:
|
||||
/**
|
||||
* The type of handshakes that will be captured.
|
||||
*/
|
||||
typedef RSNHandshake handshake_type;
|
||||
void clear_handshakes() {
|
||||
completed_handshakes_.clear();
|
||||
}
|
||||
private:
|
||||
typedef handshake_type::address_type address_type;
|
||||
typedef handshake_type::container_type eapol_list;
|
||||
typedef std::map<std::pair<address_type, address_type>, eapol_list> handshake_map;
|
||||
|
||||
/**
|
||||
* The type in which all of the captured handshakes
|
||||
* will be stored.
|
||||
*/
|
||||
typedef std::vector<handshake_type> handshakes_type;
|
||||
|
||||
/**
|
||||
* \brief Processes a packet.
|
||||
*
|
||||
* This will fetch the RSNEAPOL layer, if any, and store
|
||||
* it in an intermediate storage. When a handshake is
|
||||
* completed, it will be stored separately.
|
||||
*
|
||||
* \sa RSNHandshakeCapturer::handshakes
|
||||
*/
|
||||
bool process_packet(const PDU &pdu);
|
||||
bool do_insert(const handshake_map::key_type& key, const RSNEAPOL* eapol,
|
||||
size_t expected);
|
||||
|
||||
/**
|
||||
* \brief Retrieves the completed handshakes.
|
||||
*
|
||||
* This will return the handshakes that have been completed
|
||||
* so far. A handshake is completed when the 4-way handshake
|
||||
* is captured.
|
||||
*
|
||||
* \sa RSNHandshakeCapturer::clear_handshakes
|
||||
*/
|
||||
const handshakes_type &handshakes() const {
|
||||
return completed_handshakes_;
|
||||
}
|
||||
handshake_map handshakes_;
|
||||
handshakes_type completed_handshakes_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Clears the completed handshakes.
|
||||
*
|
||||
* Since completed handshakes are stored in a std::vector,
|
||||
* it is advisable to remove all of them once they have been
|
||||
* processed.
|
||||
*/
|
||||
void clear_handshakes() {
|
||||
completed_handshakes_.clear();
|
||||
}
|
||||
private:
|
||||
typedef handshake_type::address_type address_type;
|
||||
typedef handshake_type::container_type eapol_list;
|
||||
typedef std::map<std::pair<address_type, address_type>, eapol_list> handshake_map;
|
||||
|
||||
bool do_insert(const handshake_map::key_type &key, const RSNEAPOL *eapol,
|
||||
size_t expected);
|
||||
|
||||
handshake_map handshakes_;
|
||||
handshakes_type completed_handshakes_;
|
||||
};
|
||||
}
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_HANDSHAKE_CAPTURER_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -31,15 +31,42 @@
|
||||
#define TINS_HWADDRESS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdexcept>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include "cxxstd.h"
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <tins/cxxstd.h>
|
||||
#include <tins/macros.h>
|
||||
#if TINS_IS_CXX11
|
||||
// std::hash
|
||||
#include <memory>
|
||||
#endif // TINS_IS_CXX11
|
||||
|
||||
namespace Tins {
|
||||
namespace Internals {
|
||||
|
||||
// Defined in hw_address.cpp
|
||||
/**
|
||||
* \cond
|
||||
*/
|
||||
TINS_API std::string hw_address_to_string(const uint8_t* ptr, size_t count);
|
||||
|
||||
TINS_API void string_to_hw_address(const std::string& hw_addr, uint8_t* output,
|
||||
size_t output_size);
|
||||
|
||||
TINS_API bool hw_address_equal_compare(const uint8_t* start1, const uint8_t* end1,
|
||||
const uint8_t* start2);
|
||||
|
||||
TINS_API bool hw_address_lt_compare(const uint8_t* start1, const uint8_t* end1,
|
||||
const uint8_t* start2, const uint8_t* end2);
|
||||
|
||||
TINS_API bool hw_address_gt_compare(const uint8_t* start1, const uint8_t* end1,
|
||||
const uint8_t* start2, const uint8_t* end2);
|
||||
|
||||
/**
|
||||
* \endcond
|
||||
*/
|
||||
} // Internals
|
||||
|
||||
/**
|
||||
* \class HWAddress
|
||||
* \brief Represents a hardware address.
|
||||
@@ -60,15 +87,13 @@ namespace Tins {
|
||||
* }
|
||||
* \endcode
|
||||
*/
|
||||
template<size_t n, typename Storage = uint8_t>
|
||||
template<size_t n>
|
||||
class HWAddress {
|
||||
public:
|
||||
/**
|
||||
* \brief The type of the elements stored in the hardware address.
|
||||
*
|
||||
* This is the same as the template parameter Storage.
|
||||
*/
|
||||
typedef Storage storage_type;
|
||||
typedef uint8_t storage_type;
|
||||
|
||||
/**
|
||||
* \brief The random access iterator type.
|
||||
@@ -89,7 +114,7 @@ public:
|
||||
/**
|
||||
* \brief The broadcast address.
|
||||
*/
|
||||
static const HWAddress<n, Storage> broadcast;
|
||||
static const HWAddress<n> broadcast;
|
||||
|
||||
/**
|
||||
* \brief Constructor from a const storage_type*.
|
||||
@@ -107,10 +132,12 @@ public:
|
||||
* \param ptr The pointer from which to construct this address.
|
||||
*/
|
||||
HWAddress(const storage_type* ptr = 0) {
|
||||
if(ptr)
|
||||
std::copy(ptr, ptr + address_size, buffer);
|
||||
else
|
||||
std::fill(begin(), end(), storage_type());
|
||||
if (ptr) {
|
||||
std::memcpy(buffer_, ptr, address_size);
|
||||
}
|
||||
else {
|
||||
std::memset(buffer_, 0, address_size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,15 +151,15 @@ public:
|
||||
*
|
||||
* \param address The hex-notation address to be parsed.
|
||||
*/
|
||||
HWAddress(const std::string &address) {
|
||||
convert(address, buffer);
|
||||
HWAddress(const std::string& address) {
|
||||
Internals::string_to_hw_address(address, buffer_, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Overload provided basically for string literals.
|
||||
*
|
||||
* This constructor takes a const char array of i elements in
|
||||
* hex-notation. \sa HWAddress::HWAddress(const std::string &address)
|
||||
* hex-notation. \sa HWAddress::HWAddress(const std::string& address)
|
||||
*
|
||||
* This is mostly used when providing string literals. If this where
|
||||
* a const char*, then there would be an ambiguity when providing
|
||||
@@ -143,7 +170,7 @@ public:
|
||||
*/
|
||||
template<size_t i>
|
||||
HWAddress(const char (&address)[i]) {
|
||||
convert(address, buffer);
|
||||
Internals::string_to_hw_address(address, buffer_, n);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,19 +186,16 @@ public:
|
||||
* \param rhs The HWAddress to be constructed from.
|
||||
*/
|
||||
template<size_t i>
|
||||
HWAddress(const HWAddress<i> &rhs) {
|
||||
// Fill extra bytes
|
||||
std::fill(
|
||||
// Copy as most as we can
|
||||
std::copy(
|
||||
rhs.begin(),
|
||||
rhs.begin() + std::min(i, n),
|
||||
begin()
|
||||
),
|
||||
end(),
|
||||
0
|
||||
);
|
||||
|
||||
HWAddress(const HWAddress<i>& rhs) {
|
||||
size_t copy_threshold = i < n ? i : n;
|
||||
for (size_t index = 0; index < n; ++index) {
|
||||
if (index < copy_threshold) {
|
||||
buffer_[index] = rhs[index];
|
||||
}
|
||||
else {
|
||||
buffer_[index] = storage_type();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -181,7 +205,7 @@ public:
|
||||
* \return iterator.
|
||||
*/
|
||||
iterator begin() {
|
||||
return buffer;
|
||||
return buffer_;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -191,7 +215,7 @@ public:
|
||||
* \return const_iterator.
|
||||
*/
|
||||
const_iterator begin() const {
|
||||
return buffer;
|
||||
return buffer_;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,7 +225,7 @@ public:
|
||||
* \return iterator.
|
||||
*/
|
||||
iterator end() {
|
||||
return buffer + address_size;
|
||||
return buffer_ + address_size;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -211,7 +235,7 @@ public:
|
||||
* \return const_iterator.
|
||||
*/
|
||||
const_iterator end() const {
|
||||
return buffer + address_size;
|
||||
return buffer_ + address_size;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -221,8 +245,8 @@ public:
|
||||
*
|
||||
* \return bool indicating whether addresses are equal.
|
||||
*/
|
||||
bool operator==(const HWAddress &rhs) const {
|
||||
return std::equal(begin(), end(), rhs.begin());
|
||||
bool operator==(const HWAddress& rhs) const {
|
||||
return Internals::hw_address_equal_compare(begin(), end(), rhs.begin());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,7 +256,7 @@ public:
|
||||
*
|
||||
* \return bool indicating whether addresses are distinct.
|
||||
*/
|
||||
bool operator!=(const HWAddress &rhs) const {
|
||||
bool operator!=(const HWAddress& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
@@ -243,16 +267,89 @@ public:
|
||||
*
|
||||
* \return bool indicating whether this address is less-than rhs.
|
||||
*/
|
||||
bool operator<(const HWAddress &rhs) const {
|
||||
return std::lexicographical_compare(begin(), end(), rhs.begin(), rhs.end());
|
||||
bool operator<(const HWAddress& rhs) const {
|
||||
return Internals::hw_address_lt_compare(begin(), end(), rhs.begin(), rhs.end());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Compares this HWAddress for less-than equality.
|
||||
*
|
||||
* \param rhs The HWAddress to be compared to.
|
||||
*
|
||||
* \return bool indicating whether this address is equal or less-than rhs.
|
||||
*/
|
||||
bool operator<=(const HWAddress& rhs) const {
|
||||
return !operator>(rhs);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Compares this HWAddress for greater-than inequality.
|
||||
*
|
||||
* \param rhs The HWAddress to be compared to.
|
||||
*
|
||||
* \return bool indicating whether this address is greater-than rhs.
|
||||
*/
|
||||
bool operator>(const HWAddress& rhs) const {
|
||||
return Internals::hw_address_gt_compare(begin(), end(), rhs.begin(), rhs.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Compares this HWAddress for greater-than equality.
|
||||
*
|
||||
* \param rhs The HWAddress to be compared to.
|
||||
*
|
||||
* \return bool indicating whether this address is equal or greater-than rhs.
|
||||
*/
|
||||
bool operator>=(const HWAddress& rhs) const {
|
||||
return !operator<(rhs);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Apply a mask to this address
|
||||
*
|
||||
* \param mask The mask to be applied
|
||||
* \return The result of applying the mask to this address
|
||||
*/
|
||||
HWAddress operator&(const HWAddress& mask) const {
|
||||
HWAddress<n> output = *this;
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
output[i] = output[i] & mask[i];
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Apply a mask to this address
|
||||
*
|
||||
* \param mask The mask to be applied
|
||||
* \return The result of applying the mask to this address
|
||||
*/
|
||||
HWAddress operator|(const HWAddress& mask) const {
|
||||
HWAddress<n> output = *this;
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
output[i] = output[i] | mask[i];
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief not operator
|
||||
* \return The result of applying the mask to this address
|
||||
*/
|
||||
HWAddress operator~() const {
|
||||
HWAddress<n> output = *this;
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
output[i] = ~output[i];
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves the size of this address.
|
||||
*
|
||||
* This effectively returns the address_size constant.
|
||||
*/
|
||||
const size_t size() const {
|
||||
size_t size() const {
|
||||
return address_size;
|
||||
}
|
||||
|
||||
@@ -260,14 +357,14 @@ public:
|
||||
* \brief Indicates whether this is a broadcast address.
|
||||
*/
|
||||
bool is_broadcast() const {
|
||||
return *this == broadcast;
|
||||
return* this == broadcast;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Indicates whether this is a multicast address.
|
||||
*/
|
||||
bool is_multicast() const {
|
||||
return (buffer[0] & 0x01);
|
||||
return (*begin() & 0x01);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -283,9 +380,7 @@ public:
|
||||
* \return std::string containing the hex-notation address.
|
||||
*/
|
||||
std::string to_string() const {
|
||||
std::ostringstream oss;
|
||||
oss << *this;
|
||||
return oss.str();
|
||||
return Internals::hw_address_to_string(buffer_, size());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -294,7 +389,16 @@ public:
|
||||
* \param i The element to retrieve.
|
||||
*/
|
||||
storage_type operator[](size_t i) const {
|
||||
return buffer[i];
|
||||
return begin()[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Retrieves the i-th storage_type in this address.
|
||||
*
|
||||
* \param i The element to retrieve.
|
||||
*/
|
||||
storage_type& operator[](size_t i) {
|
||||
return begin()[i];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -304,14 +408,8 @@ public:
|
||||
* \param addr The parameter to be written.
|
||||
* \return std::ostream& pointing to the os parameter.
|
||||
*/
|
||||
friend std::ostream &operator<<(std::ostream &os, const HWAddress &addr) {
|
||||
std::transform(
|
||||
addr.begin(),
|
||||
addr.end() - 1,
|
||||
std::ostream_iterator<std::string>(os, ":"),
|
||||
&HWAddress::storage_to_string
|
||||
);
|
||||
return os << storage_to_string(addr.buffer[HWAddress::address_size-1]);
|
||||
friend std::ostream& operator<<(std::ostream& os, const HWAddress& addr) {
|
||||
return os << addr.to_string();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -325,80 +423,47 @@ public:
|
||||
* But since some PDUs return a HWAddress<> by value, this function
|
||||
* can be used to avoid temporaries.
|
||||
*
|
||||
* \param iter The output iterator in which to store this address.
|
||||
* \param output The output iterator in which to store this address.
|
||||
* \return OutputIterator pointing to one-past the last position
|
||||
* written.
|
||||
*/
|
||||
template<typename OutputIterator>
|
||||
OutputIterator copy(OutputIterator iter) const {
|
||||
return std::copy(begin(), end(), iter);
|
||||
OutputIterator copy(OutputIterator output) const {
|
||||
for (const_iterator iter = begin(); iter != end(); ++iter) {
|
||||
*output++ = *iter;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
private:
|
||||
template<typename OutputIterator>
|
||||
static void convert(const std::string &hw_addr, OutputIterator output);
|
||||
|
||||
static std::string storage_to_string(storage_type element) {
|
||||
std::ostringstream oss;
|
||||
oss << std::hex;
|
||||
if(element < 0x10)
|
||||
oss << '0';
|
||||
oss << (unsigned)element;
|
||||
return oss.str();
|
||||
static HWAddress<n> make_broadcast_address() {
|
||||
// Build a buffer made of n 0xff bytes
|
||||
uint8_t buffer[n];
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
buffer[i] = 0xff;
|
||||
}
|
||||
return HWAddress<n>(buffer);
|
||||
}
|
||||
|
||||
storage_type buffer[n];
|
||||
storage_type buffer_[n];
|
||||
};
|
||||
|
||||
template<size_t n, typename Storage>
|
||||
template<typename OutputIterator>
|
||||
void HWAddress<n, Storage>::convert(const std::string &hw_addr,
|
||||
OutputIterator output)
|
||||
{
|
||||
unsigned i(0);
|
||||
size_t count(0);
|
||||
storage_type tmp;
|
||||
while(i < hw_addr.size() && count < n) {
|
||||
const unsigned end = i+2;
|
||||
tmp = storage_type();
|
||||
while(i < end) {
|
||||
if(hw_addr[i] >= 'a' && hw_addr[i] <= 'f')
|
||||
tmp = (tmp << 4) | (hw_addr[i] - 'a' + 10);
|
||||
else if(hw_addr[i] >= 'A' && hw_addr[i] <= 'F')
|
||||
tmp = (tmp << 4) | (hw_addr[i] - 'A' + 10);
|
||||
else if(hw_addr[i] >= '0' && hw_addr[i] <= '9')
|
||||
tmp = (tmp << 4) | (hw_addr[i] - '0');
|
||||
else if(hw_addr[i] == ':')
|
||||
break;
|
||||
else
|
||||
throw std::runtime_error("Invalid byte found");
|
||||
i++;
|
||||
}
|
||||
*(output++) = tmp;
|
||||
count++;
|
||||
if(i < hw_addr.size()) {
|
||||
if(hw_addr[i] == ':')
|
||||
i++;
|
||||
else
|
||||
throw std::runtime_error("Invalid separator");
|
||||
}
|
||||
}
|
||||
while(count++ < n) {
|
||||
*(output++) = storage_type();
|
||||
}
|
||||
}
|
||||
template<size_t n>
|
||||
const HWAddress<n> HWAddress<n>::broadcast = make_broadcast_address();
|
||||
|
||||
template<size_t n, typename Storage>
|
||||
const HWAddress<n, Storage> HWAddress<n, Storage>::broadcast("ff:ff:ff:ff:ff:ff");
|
||||
} // namespace Tins
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
namespace std
|
||||
{
|
||||
namespace std {
|
||||
|
||||
// Specialization of std::hash for HWAddress
|
||||
template<size_t n>
|
||||
struct hash<Tins::HWAddress<n>> {
|
||||
size_t operator()(const Tins::HWAddress<n> &addr) const {
|
||||
size_t operator()(const Tins::HWAddress<n>& addr) const {
|
||||
return std::hash<std::string>()(addr.to_string());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
#endif
|
||||
#endif // TINS_IS_CXX11
|
||||
|
||||
#endif // TINS_HWADDRESS_H
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
// Windows likes to define macros with not-so-common-names, which break
|
||||
// this code
|
||||
#ifdef WIN32
|
||||
#ifdef _WIN32
|
||||
#ifdef TIMESTAMP_REQUEST
|
||||
#undef TIMESTAMP_REQUEST
|
||||
#endif // TIMESTAMP_REQUEST
|
||||
@@ -40,369 +40,474 @@
|
||||
#ifdef TIMESTAMP_REPLY
|
||||
#undef TIMESTAMP_REPLY
|
||||
#endif // TIMESTAMP_REPLY
|
||||
#endif // WIN32
|
||||
#endif // _WIN32
|
||||
|
||||
#include "macros.h"
|
||||
#include "pdu.h"
|
||||
#include "endianness.h"
|
||||
#include "ip_address.h"
|
||||
#include <tins/macros.h>
|
||||
#include <tins/pdu.h>
|
||||
#include <tins/endianness.h>
|
||||
#include <tins/ip_address.h>
|
||||
#include <tins/icmp_extension.h>
|
||||
|
||||
namespace Tins {
|
||||
namespace Memory {
|
||||
|
||||
class InputMemoryStream;
|
||||
|
||||
} // Memory
|
||||
|
||||
/**
|
||||
* \class ICMP
|
||||
* \brief Class that represents an ICMP PDU.
|
||||
*
|
||||
* ICMP is the representation of the ICMP PDU. Instances of this class
|
||||
* must be sent over a level 3 PDU, this will otherwise fail.
|
||||
*/
|
||||
class TINS_API ICMP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::ICMP;
|
||||
|
||||
/**
|
||||
* The type used to store addresses.
|
||||
*/
|
||||
typedef IPv4Address address_type;
|
||||
|
||||
/** \brief ICMP flags
|
||||
*/
|
||||
enum Flags {
|
||||
ECHO_REPLY = 0,
|
||||
DEST_UNREACHABLE = 3,
|
||||
SOURCE_QUENCH = 4,
|
||||
REDIRECT = 5,
|
||||
ECHO_REQUEST = 8,
|
||||
TIME_EXCEEDED = 11,
|
||||
PARAM_PROBLEM = 12,
|
||||
TIMESTAMP_REQUEST = 13,
|
||||
TIMESTAMP_REPLY = 14,
|
||||
INFO_REQUEST = 15,
|
||||
INFO_REPLY = 16,
|
||||
ADDRESS_MASK_REQUEST = 17,
|
||||
ADDRESS_MASK_REPLY = 18,
|
||||
EXTENDED_ECHO_REQUEST = 42,
|
||||
EXTENDED_ECHO_REPLY = 43
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Extracts metadata for this protocol based on the buffer provided
|
||||
*
|
||||
* \param buffer Pointer to a buffer
|
||||
* \param total_sz Size of the buffer pointed by buffer
|
||||
*/
|
||||
static metadata extract_metadata(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Creates an instance of ICMP.
|
||||
*
|
||||
* If no flag is specified, then ECHO_REQUEST will be used.
|
||||
* \param flag The type flag which will be set.
|
||||
*/
|
||||
ICMP(Flags flag = ECHO_REQUEST);
|
||||
|
||||
/**
|
||||
* \brief Constructs an ICMP object from a buffer.
|
||||
*
|
||||
* If there is not enough size for an ICMP header, a
|
||||
* malformed_packet exception is thrown.
|
||||
*
|
||||
* Any extra data in the buffer will be stored in a RawPDU.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
ICMP(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Sets the code field.
|
||||
*
|
||||
* \param new_code The code which will be stored in the ICMP struct.
|
||||
*/
|
||||
void code(uint8_t new_code);
|
||||
|
||||
/** \brief Sets the type field.
|
||||
*
|
||||
* \param type The type which will be stored in the ICMP struct.
|
||||
*/
|
||||
void type(Flags type);
|
||||
|
||||
/**
|
||||
* \brief Setter for the id field.
|
||||
*
|
||||
* \param new_id uint16_t with the new id.
|
||||
*/
|
||||
void id(uint16_t new_id);
|
||||
|
||||
/**
|
||||
* \brief Setter for the sequence field.
|
||||
*
|
||||
* \param new_seq uint16_t with the new sequence.
|
||||
*/
|
||||
void sequence(uint16_t new_seq);
|
||||
|
||||
/**
|
||||
* \brief Setter for the gateway field.
|
||||
*
|
||||
* \param new_gw The new value for the gateway field.
|
||||
*/
|
||||
void gateway(address_type new_gw);
|
||||
|
||||
/**
|
||||
* \brief Setter for the mtu field.
|
||||
*
|
||||
* \param new_mtu uint16_t with the new sequence.
|
||||
*/
|
||||
void mtu(uint16_t new_mtu);
|
||||
|
||||
/**
|
||||
* \brief Setter for the pointer field.
|
||||
*
|
||||
* \param new_pointer uint8_t with the new pointer.
|
||||
*/
|
||||
void pointer(uint8_t new_pointer);
|
||||
|
||||
/**
|
||||
* \brief Setter for the original timestamp field.
|
||||
*
|
||||
* \param new_timestamp the value to be set.
|
||||
*/
|
||||
void original_timestamp(uint32_t new_timestamp);
|
||||
|
||||
/**
|
||||
* \brief Setter for the receive timestamp field.
|
||||
*
|
||||
* \param new_timestamp the value to be set.
|
||||
*/
|
||||
void receive_timestamp(uint32_t new_timestamp);
|
||||
|
||||
/**
|
||||
* \brief Setter for the transmit timestamp field.
|
||||
*
|
||||
* \param new_timestamp the value to be set.
|
||||
*/
|
||||
void transmit_timestamp(uint32_t new_timestamp);
|
||||
|
||||
/**
|
||||
* \brief Setter for the address mask field.
|
||||
*
|
||||
* \param new_mask the value to be set.
|
||||
*/
|
||||
void address_mask(address_type new_mask);
|
||||
|
||||
/**
|
||||
* \brief Sets echo request flag for this PDU.
|
||||
*
|
||||
* \param id The identifier for this request.
|
||||
* \param seq The sequence number for this request.
|
||||
*/
|
||||
void set_echo_request(uint16_t id, uint16_t seq);
|
||||
|
||||
/**
|
||||
* \brief Sets echo reply flag for this PDU.
|
||||
*
|
||||
* \param id The identifier for this request.
|
||||
* \param seq The sequence number for this request.
|
||||
*/
|
||||
void set_echo_reply(uint16_t id, uint16_t seq);
|
||||
|
||||
/**
|
||||
* \brief Sets information request flag for this PDU.
|
||||
*
|
||||
* \param id The identifier for this request.
|
||||
* \param seq The sequence number for this request.
|
||||
*/
|
||||
void set_info_request(uint16_t id, uint16_t seq);
|
||||
|
||||
/**
|
||||
* \brief Sets information reply flag for this PDU.
|
||||
*
|
||||
* \param id The identifier for this request.
|
||||
* \param seq The sequence number for this request.
|
||||
*/
|
||||
void set_info_reply(uint16_t id, uint16_t seq);
|
||||
|
||||
/**
|
||||
* \brief Sets destination unreachable for this PDU.
|
||||
*/
|
||||
void set_dest_unreachable();
|
||||
|
||||
/**
|
||||
* \brief Sets time exceeded flag for this PDU.
|
||||
*
|
||||
* \param ttl_exceeded If true this PDU will represent a ICMP ttl
|
||||
* exceeded, otherwise it will represent a fragment reassembly
|
||||
* time exceeded.
|
||||
*/
|
||||
void set_time_exceeded(bool ttl_exceeded = true);
|
||||
|
||||
/**
|
||||
* \brief Sets parameter problem flag for this PDU.
|
||||
*
|
||||
* \param set_pointer Indicates whether a pointer to the bad octet
|
||||
* is provided.
|
||||
* \param bad_octet Identifies the octet in which the error was
|
||||
* detected. If set_pointer == false, it is ignored.
|
||||
*/
|
||||
void set_param_problem(bool set_pointer = false, uint8_t bad_octet = 0);
|
||||
|
||||
/**
|
||||
* \brief Sets source quench flag for this PDU.
|
||||
*/
|
||||
void set_source_quench();
|
||||
|
||||
/**
|
||||
* \brief Sets redirect flag for this PDU.
|
||||
*
|
||||
* \param icode The code to be set.
|
||||
* \param address Address of the gateway to which traffic should
|
||||
* be sent.
|
||||
*/
|
||||
void set_redirect(uint8_t icode, address_type address);
|
||||
|
||||
/**
|
||||
* \brief Getter for the ICMP type flag.
|
||||
*
|
||||
* \return The type flag for this ICMP PDU.
|
||||
*/
|
||||
Flags type() const {
|
||||
return (Flags)header_.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the ICMP code flag.
|
||||
*
|
||||
* \return The code flag for this ICMP PDU.
|
||||
*/
|
||||
uint8_t code() const {
|
||||
return header_.code;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the checksum field.
|
||||
*
|
||||
* \return Returns the checksum as an unit16_t.
|
||||
*/
|
||||
uint16_t checksum() const {
|
||||
return Endian::be_to_host(header_.check);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the echo id.
|
||||
*
|
||||
* \return Returns the echo id.
|
||||
*/
|
||||
uint16_t id() const {
|
||||
return Endian::be_to_host(header_.un.echo.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the echo sequence number.
|
||||
*
|
||||
* \return Returns the echo sequence number.
|
||||
*/
|
||||
uint16_t sequence() const {
|
||||
return Endian::be_to_host(header_.un.echo.sequence);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the gateway field.
|
||||
*
|
||||
* \return Returns the gateway field value.
|
||||
*/
|
||||
address_type gateway() const {
|
||||
return address_type(header_.un.gateway);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the pointer field.
|
||||
*
|
||||
* \return Returns the pointer field value.
|
||||
*/
|
||||
uint8_t pointer() const {
|
||||
return header_.un.rfc4884.pointer;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the length field.
|
||||
*
|
||||
* \return Returns the length field value.
|
||||
*/
|
||||
uint8_t length() const {
|
||||
return header_.un.rfc4884.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the mtu field.
|
||||
*
|
||||
* \return Returns the mtu field value.
|
||||
*/
|
||||
uint16_t mtu() const {
|
||||
return Endian::be_to_host(header_.un.frag.mtu);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the original timestamp field.
|
||||
*
|
||||
* \return Returns the original timestamp value.
|
||||
*/
|
||||
uint32_t original_timestamp() const {
|
||||
return Endian::be_to_host(orig_timestamp_or_address_mask_);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the receive timestamp field.
|
||||
*
|
||||
* \return Returns the receive timestamp value.
|
||||
*/
|
||||
uint32_t receive_timestamp() const {
|
||||
return Endian::be_to_host(recv_timestamp_);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the transmit timestamp field.
|
||||
*
|
||||
* \return Returns the transmit timestamp value.
|
||||
*/
|
||||
uint32_t transmit_timestamp() const {
|
||||
return Endian::be_to_host(trans_timestamp_);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the address mask field.
|
||||
*
|
||||
* \return Returns the address mask value.
|
||||
*/
|
||||
address_type address_mask() const {
|
||||
return address_type(orig_timestamp_or_address_mask_);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
* This method overrides PDU::header_size. This size includes the
|
||||
* payload and options size.
|
||||
*
|
||||
* \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Returns the trailer size.
|
||||
*
|
||||
* This method overrides PDU::trailer_size. This size will hold the extensions size
|
||||
*
|
||||
* \sa PDU::header_size
|
||||
*/
|
||||
uint32_t trailer_size() const;
|
||||
|
||||
/**
|
||||
* \brief Check whether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t* ptr, uint32_t total_sz) const;
|
||||
|
||||
/**
|
||||
* \class ICMP
|
||||
* \brief Class that represents an ICMP PDU.
|
||||
* \brief Getter for the extensions field.
|
||||
*
|
||||
* ICMP is the representation of the ICMP PDU. Instances of this class
|
||||
* must be sent over a level 3 PDU, this will otherwise fail.
|
||||
* \return The extensions field
|
||||
*/
|
||||
class ICMP : public PDU {
|
||||
public:
|
||||
/**
|
||||
* \brief This PDU's flag.
|
||||
*/
|
||||
static const PDU::PDUType pdu_flag = PDU::ICMP;
|
||||
|
||||
/**
|
||||
* The type used to store addresses.
|
||||
*/
|
||||
typedef IPv4Address address_type;
|
||||
const ICMPExtensionsStructure& extensions() const {
|
||||
return extensions_;
|
||||
}
|
||||
|
||||
/** \brief ICMP flags
|
||||
*/
|
||||
enum Flags {
|
||||
ECHO_REPLY = 0,
|
||||
DEST_UNREACHABLE = 3,
|
||||
SOURCE_QUENCH = 4,
|
||||
REDIRECT = 5,
|
||||
ECHO_REQUEST = 8,
|
||||
TIME_EXCEEDED = 11,
|
||||
PARAM_PROBLEM = 12,
|
||||
TIMESTAMP_REQUEST = 13,
|
||||
TIMESTAMP_REPLY = 14,
|
||||
INFO_REQUEST = 15,
|
||||
INFO_REPLY = 16,
|
||||
ADDRESS_MASK_REQUEST = 17,
|
||||
ADDRESS_MASK_REPLY = 18
|
||||
};
|
||||
/**
|
||||
* \brief Getter for the extensions field.
|
||||
*
|
||||
* \return The extensions field
|
||||
*/
|
||||
ICMPExtensionsStructure& extensions() {
|
||||
return extensions_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Creates an instance of ICMP.
|
||||
*
|
||||
* If no flag is specified, then ECHO_REQUEST will be used.
|
||||
* \param flag The type flag which will be set.
|
||||
*/
|
||||
ICMP(Flags flag = ECHO_REQUEST);
|
||||
/**
|
||||
* \brief Indicates whether this object contains ICMP extensions
|
||||
*/
|
||||
bool has_extensions() const {
|
||||
return !extensions_.extensions().empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Constructs an ICMP object from a buffer.
|
||||
*
|
||||
* If there is not enough size for an ICMP header, a
|
||||
* malformed_packet exception is thrown.
|
||||
*
|
||||
* Any extra data in the buffer will be stored in a RawPDU.
|
||||
*
|
||||
* \param buffer The buffer from which this PDU will be constructed.
|
||||
* \param total_sz The total size of the buffer.
|
||||
*/
|
||||
ICMP(const uint8_t *buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Sets the code field.
|
||||
*
|
||||
* \param new_code The code which will be stored in the ICMP struct.
|
||||
*/
|
||||
void code(uint8_t new_code);
|
||||
/**
|
||||
* \brief Sets whether the length field will be set for packets that use it
|
||||
*
|
||||
* As defined in RFC 4884, some ICMP packet types can have a length field. This
|
||||
* method controlers whether the length field is set or not.
|
||||
*
|
||||
* Note that this only indicates that the packet should use this field. The
|
||||
* actual value will be set during the packet's serialization.
|
||||
*
|
||||
* Note that, in order to br RFC compliant, if the size of the encapsulated
|
||||
* PDU is greater than 128, the length field will always be set, regardless
|
||||
* of whether this method was called or not.
|
||||
*
|
||||
* /param value true iff the length field should be set appropriately
|
||||
*/
|
||||
void use_length_field(bool value);
|
||||
|
||||
/** \brief Sets the type field.
|
||||
*
|
||||
* \param type The type which will be stored in the ICMP struct.
|
||||
*/
|
||||
void type(Flags type);
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
*
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const {
|
||||
return pdu_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Setter for the id field.
|
||||
*
|
||||
* \param new_id uint16_t with the new id.
|
||||
*/
|
||||
void id(uint16_t new_id);
|
||||
|
||||
/**
|
||||
* \brief Setter for the sequence field.
|
||||
*
|
||||
* \param new_seq uint16_t with the new sequence.
|
||||
*/
|
||||
void sequence(uint16_t new_seq);
|
||||
|
||||
/**
|
||||
* \brief Setter for the gateway field.
|
||||
*
|
||||
* \param new_gw The new value for the gateway field.
|
||||
*/
|
||||
void gateway(address_type new_gw);
|
||||
|
||||
/**
|
||||
* \brief Setter for the mtu field.
|
||||
*
|
||||
* \param new_mtu uint16_t with the new sequence.
|
||||
*/
|
||||
void mtu(uint16_t new_mtu);
|
||||
|
||||
/**
|
||||
* \brief Setter for the pointer field.
|
||||
*
|
||||
* \param new_pointer uint8_t with the new pointer.
|
||||
*/
|
||||
void pointer(uint8_t new_pointer);
|
||||
|
||||
/**
|
||||
* \brief Setter for the original timestamp field.
|
||||
*
|
||||
* \param new_timestamp the value to be set.
|
||||
*/
|
||||
void original_timestamp(uint32_t new_timestamp);
|
||||
|
||||
/**
|
||||
* \brief Setter for the receive timestamp field.
|
||||
*
|
||||
* \param new_timestamp the value to be set.
|
||||
*/
|
||||
void receive_timestamp(uint32_t new_timestamp);
|
||||
|
||||
/**
|
||||
* \brief Setter for the transmit timestamp field.
|
||||
*
|
||||
* \param new_timestamp the value to be set.
|
||||
*/
|
||||
void transmit_timestamp(uint32_t new_timestamp);
|
||||
|
||||
/**
|
||||
* \brief Setter for the address mask field.
|
||||
*
|
||||
* \param new_mask the value to be set.
|
||||
*/
|
||||
void address_mask(address_type new_mask);
|
||||
|
||||
/**
|
||||
* \brief Sets echo request flag for this PDU.
|
||||
*
|
||||
* \param id The identifier for this request.
|
||||
* \param seq The sequence number for this request.
|
||||
*/
|
||||
void set_echo_request(uint16_t id, uint16_t seq);
|
||||
|
||||
/**
|
||||
* \brief Sets echo reply flag for this PDU.
|
||||
*
|
||||
* \param id The identifier for this request.
|
||||
* \param seq The sequence number for this request.
|
||||
*/
|
||||
void set_echo_reply(uint16_t id, uint16_t seq);
|
||||
|
||||
/**
|
||||
* \brief Sets information request flag for this PDU.
|
||||
*
|
||||
* \param id The identifier for this request.
|
||||
* \param seq The sequence number for this request.
|
||||
*/
|
||||
void set_info_request(uint16_t id, uint16_t seq);
|
||||
|
||||
/**
|
||||
* \brief Sets information reply flag for this PDU.
|
||||
*
|
||||
* \param id The identifier for this request.
|
||||
* \param seq The sequence number for this request.
|
||||
*/
|
||||
void set_info_reply(uint16_t id, uint16_t seq);
|
||||
|
||||
/**
|
||||
* \brief Sets destination unreachable for this PDU.
|
||||
*/
|
||||
void set_dest_unreachable();
|
||||
|
||||
/**
|
||||
* \brief Sets time exceeded flag for this PDU.
|
||||
*
|
||||
* \param ttl_exceeded If true this PDU will represent a ICMP ttl
|
||||
* exceeded, otherwise it will represent a fragment reassembly
|
||||
* time exceeded.
|
||||
*/
|
||||
void set_time_exceeded(bool ttl_exceeded = true);
|
||||
|
||||
/**
|
||||
* \brief Sets parameter problem flag for this PDU.
|
||||
*
|
||||
* \param set_pointer Indicates wether a pointer to the bad octet
|
||||
* is provided.
|
||||
* \param bad_octet Identifies the octet in which the error was
|
||||
* detected. If set_pointer == false, it is ignored.
|
||||
*/
|
||||
void set_param_problem(bool set_pointer = false, uint8_t bad_octet = 0);
|
||||
|
||||
/**
|
||||
* \brief Sets source quench flag for this PDU.
|
||||
*/
|
||||
void set_source_quench();
|
||||
|
||||
/**
|
||||
* \brief Sets redirect flag for this PDU.
|
||||
*
|
||||
* \param icode The code to be set.
|
||||
* \param address Address of the gateway to which traffic should
|
||||
* be sent.
|
||||
*/
|
||||
void set_redirect(uint8_t icode, address_type address);
|
||||
|
||||
/**
|
||||
* \brief Getter for the ICMP type flag.
|
||||
*
|
||||
* \return The type flag for this ICMP PDU.
|
||||
*/
|
||||
Flags type() const { return (Flags)_icmp.type; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the ICMP code flag.
|
||||
*
|
||||
* \return The code flag for this ICMP PDU.
|
||||
*/
|
||||
uint8_t code() const { return _icmp.code; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the checksum field.
|
||||
*
|
||||
* \return Returns the checksum as an unit16_t.
|
||||
*/
|
||||
uint16_t checksum() const { return Endian::be_to_host(_icmp.check); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the echo id.
|
||||
*
|
||||
* \return Returns the echo id.
|
||||
*/
|
||||
uint16_t id() const { return Endian::be_to_host(_icmp.un.echo.id); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the echo sequence number.
|
||||
*
|
||||
* \return Returns the echo sequence number.
|
||||
*/
|
||||
uint16_t sequence() const { return Endian::be_to_host(_icmp.un.echo.sequence); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the gateway field.
|
||||
*
|
||||
* \return Returns the gateway field value.
|
||||
*/
|
||||
address_type gateway() const {
|
||||
return address_type(Endian::be_to_host(_icmp.un.gateway));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the pointer field.
|
||||
*
|
||||
* \return Returns the pointer field value.
|
||||
*/
|
||||
uint8_t pointer() const { return this->_icmp.un.pointer; }
|
||||
|
||||
/**
|
||||
* \brief Getter for the mtu field.
|
||||
*
|
||||
* \return Returns the mtu field value.
|
||||
*/
|
||||
uint16_t mtu() const { return Endian::be_to_host(_icmp.un.frag.mtu); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the original timestamp field.
|
||||
*
|
||||
* \return Returns the original timestamp value.
|
||||
*/
|
||||
uint32_t original_timestamp() const { return Endian::be_to_host(_orig_timestamp_or_address_mask); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the receive timestamp field.
|
||||
*
|
||||
* \return Returns the receive timestamp value.
|
||||
*/
|
||||
uint32_t receive_timestamp() const { return Endian::be_to_host(_recv_timestamp); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the transmit timestamp field.
|
||||
*
|
||||
* \return Returns the transmit timestamp value.
|
||||
*/
|
||||
uint32_t transmit_timestamp() const { return Endian::be_to_host(_trans_timestamp); }
|
||||
|
||||
/**
|
||||
* \brief Getter for the address mask field.
|
||||
*
|
||||
* \return Returns the address mask value.
|
||||
*/
|
||||
address_type address_mask() const {
|
||||
return address_type(Endian::be_to_host(_orig_timestamp_or_address_mask));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the header size.
|
||||
*
|
||||
* This metod overrides PDU::header_size. This size includes the
|
||||
* payload and options size. \sa PDU::header_size
|
||||
*/
|
||||
uint32_t header_size() const;
|
||||
|
||||
/**
|
||||
* \brief Check wether ptr points to a valid response for this PDU.
|
||||
*
|
||||
* \sa PDU::matches_response
|
||||
* \param ptr The pointer to the buffer.
|
||||
* \param total_sz The size of the buffer.
|
||||
*/
|
||||
bool matches_response(const uint8_t *ptr, uint32_t total_sz) const;
|
||||
|
||||
/**
|
||||
* \brief Getter for the PDU's type.
|
||||
*
|
||||
* \sa PDU::pdu_type
|
||||
*/
|
||||
PDUType pdu_type() const { return PDU::ICMP; }
|
||||
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
ICMP *clone() const {
|
||||
return new ICMP(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct icmphdr {
|
||||
uint8_t type;
|
||||
uint8_t code;
|
||||
uint16_t check;
|
||||
union {
|
||||
struct {
|
||||
uint16_t id;
|
||||
uint16_t sequence;
|
||||
} echo;
|
||||
uint32_t gateway;
|
||||
struct {
|
||||
uint16_t unused;
|
||||
uint16_t mtu;
|
||||
} frag;
|
||||
/**
|
||||
* \sa PDU::clone
|
||||
*/
|
||||
ICMP* clone() const {
|
||||
return new ICMP(*this);
|
||||
}
|
||||
private:
|
||||
TINS_BEGIN_PACK
|
||||
struct icmp_header {
|
||||
uint8_t type;
|
||||
uint8_t code;
|
||||
uint16_t check;
|
||||
union {
|
||||
struct {
|
||||
uint16_t id;
|
||||
uint16_t sequence;
|
||||
} echo;
|
||||
uint32_t gateway;
|
||||
struct {
|
||||
uint16_t unused;
|
||||
uint16_t mtu;
|
||||
} frag;
|
||||
struct {
|
||||
uint8_t pointer;
|
||||
} un;
|
||||
} TINS_END_PACK;
|
||||
uint8_t length;
|
||||
uint16_t unused;
|
||||
} rfc4884;
|
||||
} un;
|
||||
} TINS_END_PACK;
|
||||
|
||||
void checksum(uint16_t new_check);
|
||||
|
||||
/** \brief Serialices this ICMP PDU.
|
||||
* \param buffer The buffer in which the PDU will be serialized.
|
||||
* \param total_sz The size available in the buffer.
|
||||
* \param parent The PDU that's one level below this one on the stack.
|
||||
*/
|
||||
void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent);
|
||||
void checksum(uint16_t new_check);
|
||||
void write_serialization(uint8_t* buffer, uint32_t total_sz);
|
||||
uint32_t get_adjusted_inner_pdu_size() const;
|
||||
void try_parse_extensions(Memory::InputMemoryStream& stream);
|
||||
bool are_extensions_allowed() const;
|
||||
|
||||
icmphdr _icmp;
|
||||
uint32_t _orig_timestamp_or_address_mask, _recv_timestamp, _trans_timestamp;
|
||||
};
|
||||
}
|
||||
icmp_header header_;
|
||||
uint32_t orig_timestamp_or_address_mask_;
|
||||
uint32_t recv_timestamp_;
|
||||
uint32_t trans_timestamp_;
|
||||
ICMPExtensionsStructure extensions_;
|
||||
};
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_ICMP_H
|
||||
|
||||
307
include/tins/icmp_extension.h
Normal file
307
include/tins/icmp_extension.h
Normal file
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TINS_ICMP_EXTENSION_H
|
||||
#define TINS_ICMP_EXTENSION_H
|
||||
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include <tins/macros.h>
|
||||
#include <tins/small_uint.h>
|
||||
#include <tins/endianness.h>
|
||||
|
||||
namespace Tins {
|
||||
|
||||
class MPLS;
|
||||
|
||||
/**
|
||||
* \brief Class that represents an ICMP extension object
|
||||
*/
|
||||
class TINS_API ICMPExtension {
|
||||
public:
|
||||
/**
|
||||
* The type used to store the payload
|
||||
*/
|
||||
typedef std::vector<uint8_t> payload_type;
|
||||
|
||||
/**
|
||||
* The type that will be returned when serializing an extensions
|
||||
* structure object
|
||||
*/
|
||||
typedef std::vector<uint8_t> serialization_type;
|
||||
|
||||
/**
|
||||
* \brief Default constructor
|
||||
*/
|
||||
ICMPExtension();
|
||||
|
||||
/**
|
||||
* \brief Constructor taking class and type
|
||||
*
|
||||
* \param ext_class The extension class
|
||||
* \param ext_type The extension sub-type
|
||||
*/
|
||||
ICMPExtension(uint8_t ext_class, uint8_t ext_type);
|
||||
|
||||
/**
|
||||
* \brief Constructs an ICMP extension from a buffer
|
||||
*
|
||||
* \param buffer The input buffer
|
||||
* \param total_sz The input buffer size
|
||||
*/
|
||||
ICMPExtension(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Setter for the extension class field
|
||||
*
|
||||
* \param value The new extension class field value
|
||||
*/
|
||||
void extension_class(uint8_t value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the extension sub-type field
|
||||
*
|
||||
* \param value The new extension sub-type field value
|
||||
*/
|
||||
void extension_type(uint8_t value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the payload field
|
||||
*
|
||||
* \param value The new payload field value
|
||||
*/
|
||||
void payload(const payload_type& value);
|
||||
|
||||
/**
|
||||
* \brief Getter for the extension class field
|
||||
*
|
||||
* \return The extension class field value
|
||||
*/
|
||||
uint8_t extension_class() const {
|
||||
return extension_class_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the extension sub-type field
|
||||
*
|
||||
* \return The extension sub-type field value
|
||||
*/
|
||||
uint8_t extension_type() const {
|
||||
return extension_type_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the extension payload field
|
||||
*
|
||||
* \return The extension payload field value
|
||||
*/
|
||||
const payload_type& payload() const {
|
||||
return payload_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Gets the size of this ICMP extension
|
||||
*
|
||||
* This returns the basic header size + the payload size
|
||||
*
|
||||
* \return The size of this extension
|
||||
*/
|
||||
uint32_t size() const;
|
||||
|
||||
/**
|
||||
* \brief Serializes this extension into a buffer
|
||||
*
|
||||
* \param buffer The output buffer in which to store the serialization
|
||||
* \param buffer_size The size of the output buffer
|
||||
*/
|
||||
void serialize(uint8_t* buffer, uint32_t buffer_size) const;
|
||||
|
||||
/**
|
||||
* \brief Serializes this extension object
|
||||
*
|
||||
* \return The serialized extension
|
||||
*/
|
||||
serialization_type serialize() const;
|
||||
private:
|
||||
static const uint32_t BASE_HEADER_SIZE;
|
||||
|
||||
payload_type payload_;
|
||||
uint8_t extension_class_, extension_type_;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Class that represents an ICMP extensions structure
|
||||
*/
|
||||
class TINS_API ICMPExtensionsStructure {
|
||||
public:
|
||||
/**
|
||||
* The minimum ICMP payload size that has to be present when the PDU
|
||||
* contains extensions.
|
||||
*/
|
||||
static const uint32_t MINIMUM_ICMP_PAYLOAD;
|
||||
|
||||
/**
|
||||
* The type that will be returned when serializing an extensions
|
||||
* structure object
|
||||
*/
|
||||
typedef ICMPExtension::serialization_type serialization_type;
|
||||
|
||||
/**
|
||||
* The type used to store the list of ICMP extensions in this structure
|
||||
*/
|
||||
typedef std::vector<ICMPExtension> extensions_type;
|
||||
|
||||
/**
|
||||
* \brief Default constructor
|
||||
*
|
||||
* This sets the version to 2, as specified in RFC 4884
|
||||
*/
|
||||
ICMPExtensionsStructure();
|
||||
|
||||
/**
|
||||
* \brief Constructor from a buffer.
|
||||
*
|
||||
* This constructor will find, parse and store the extension
|
||||
* stack in the buffer.
|
||||
*/
|
||||
ICMPExtensionsStructure(const uint8_t* buffer, uint32_t total_sz);
|
||||
|
||||
/**
|
||||
* \brief Setter for the version field
|
||||
*
|
||||
* \param value The new version field value
|
||||
*/
|
||||
void version(small_uint<4> value);
|
||||
|
||||
/**
|
||||
* \brief Setter for the reserved field
|
||||
*
|
||||
* \param value The new reserved field value
|
||||
*/
|
||||
void reserved(small_uint<12> value);
|
||||
|
||||
/**
|
||||
* \brief Getter for the version field
|
||||
*
|
||||
* \return The version field value
|
||||
*/
|
||||
small_uint<4> version() const {
|
||||
uint16_t value = Endian::be_to_host(version_and_reserved_);
|
||||
return (value >> 12) & 0xf;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the reserved field
|
||||
*
|
||||
* \return The reserved field value
|
||||
*/
|
||||
small_uint<12> reserved() const {
|
||||
uint16_t value = Endian::be_to_host(version_and_reserved_);
|
||||
return value & 0xfff;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the checksum field
|
||||
*
|
||||
* \return The checksum field value
|
||||
*/
|
||||
uint16_t checksum() const {
|
||||
return Endian::be_to_host(checksum_);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Getter for the extensions stored by this structure
|
||||
*
|
||||
* \return The extensions stored in this structure
|
||||
*/
|
||||
const extensions_type& extensions() const {
|
||||
return extensions_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Adds an extension to this structure
|
||||
*
|
||||
* \param extension The extension to be added
|
||||
*/
|
||||
void add_extension(const ICMPExtension& extension);
|
||||
|
||||
/**
|
||||
* \brief Adds an MPLS extension to this structure
|
||||
*
|
||||
* This will construct an extension using the provided MPLS packet as
|
||||
* its payload. The class and type fields will be set appropriately.
|
||||
*
|
||||
* \param extension The MPLS payload to be used for the new extension
|
||||
*/
|
||||
void add_extension(MPLS& mpls);
|
||||
|
||||
/**
|
||||
* \brief Gets the size of this ICMP extensions structure
|
||||
*
|
||||
* \return The size of this structure
|
||||
*/
|
||||
uint32_t size() const;
|
||||
|
||||
/**
|
||||
* \brief Serializes this extension structure into a buffer
|
||||
*
|
||||
* \param buffer The output buffer in which to store the serialization
|
||||
* \param buffer_size The size of the output buffer
|
||||
*/
|
||||
void serialize(uint8_t* buffer, uint32_t buffer_size);
|
||||
|
||||
/**
|
||||
* \brief Serializes this extension structure
|
||||
*
|
||||
* \return The serialized extension structure
|
||||
*/
|
||||
serialization_type serialize();
|
||||
|
||||
/**
|
||||
* \brief Validates if the given input contains a valid extension structure
|
||||
*
|
||||
* The validation is performed by calculating the checksum of the input
|
||||
* and comparing to the checksum value in the input buffer.
|
||||
*
|
||||
* \param buffer The input buffer
|
||||
* \param total_sz The size of the input buffer
|
||||
* \return true iff the buffer contains a valid ICMP extensions structure
|
||||
*/
|
||||
static bool validate_extensions(const uint8_t* buffer, uint32_t total_sz);
|
||||
private:
|
||||
static const uint32_t BASE_HEADER_SIZE;
|
||||
|
||||
uint16_t version_and_reserved_;
|
||||
uint16_t checksum_;
|
||||
extensions_type extensions_;
|
||||
};
|
||||
|
||||
} // Tins
|
||||
|
||||
#endif // TINS_ICMP_EXTENSION_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -30,7 +30,7 @@
|
||||
#ifndef TINS_IEEE802_3_H
|
||||
#define TINS_IEEE802_3_H
|
||||
|
||||
#include "dot3.h"
|
||||
#include <tins/dot3.h>
|
||||
|
||||
namespace Tins {
|
||||
typedef Dot3 IEEE802_3;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Matias Fontanini
|
||||
* Copyright (c) 2017, Matias Fontanini
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -30,217 +30,11 @@
|
||||
#ifndef TINS_INTERNALS_H
|
||||
#define TINS_INTERNALS_H
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
#include <type_traits>
|
||||
#endif
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include "constants.h"
|
||||
#include "pdu.h"
|
||||
#include "hw_address.h"
|
||||
|
||||
/**
|
||||
* \cond
|
||||
*/
|
||||
namespace Tins {
|
||||
class IPv4Address;
|
||||
class IPv6Address;
|
||||
|
||||
namespace Internals {
|
||||
template<size_t n>
|
||||
class byte_array {
|
||||
public:
|
||||
typedef uint8_t* iterator;
|
||||
typedef const uint8_t* const_iterator;
|
||||
|
||||
byte_array() {
|
||||
std::fill(begin(), end(), 0);
|
||||
}
|
||||
|
||||
template<typename InputIterator>
|
||||
byte_array(InputIterator start, InputIterator last) {
|
||||
std::copy(start, last, data);
|
||||
}
|
||||
|
||||
template<typename InputIterator>
|
||||
byte_array(InputIterator start) {
|
||||
std::copy(start, n, data);
|
||||
}
|
||||
|
||||
uint8_t &operator[](size_t i) {
|
||||
return data[i];
|
||||
}
|
||||
|
||||
uint8_t operator[](size_t i) const{
|
||||
return data[i];
|
||||
}
|
||||
|
||||
iterator begin() {
|
||||
return data;
|
||||
}
|
||||
|
||||
iterator end() {
|
||||
return data + n;
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
return data;
|
||||
}
|
||||
|
||||
const_iterator end() const {
|
||||
return data + n;
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return n;
|
||||
}
|
||||
private:
|
||||
uint8_t data[n];
|
||||
};
|
||||
|
||||
void skip_line(std::istream &input);
|
||||
bool from_hex(const std::string &str, uint32_t &result);
|
||||
|
||||
template<bool, typename T = void>
|
||||
struct enable_if {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct enable_if<false, T> {
|
||||
|
||||
};
|
||||
|
||||
PDU *pdu_from_flag(Constants::Ethernet::e flag, const uint8_t *buffer,
|
||||
uint32_t size, bool rawpdu_on_no_match = true);
|
||||
PDU *pdu_from_flag(Constants::IP::e flag, const uint8_t *buffer,
|
||||
uint32_t size, bool rawpdu_on_no_match = true);
|
||||
PDU *pdu_from_dlt_flag(int flag, const uint8_t *buffer,
|
||||
uint32_t size, bool rawpdu_on_no_match = true);
|
||||
PDU *pdu_from_flag(PDU::PDUType type, const uint8_t *buffer, uint32_t size);
|
||||
|
||||
Constants::Ethernet::e pdu_flag_to_ether_type(PDU::PDUType flag);
|
||||
Constants::IP::e pdu_flag_to_ip_type(PDU::PDUType flag);
|
||||
|
||||
template<typename T>
|
||||
bool increment_buffer(T &addr) {
|
||||
typename T::iterator it = addr.end() - 1;
|
||||
while(it >= addr.begin() && *it == 0xff) {
|
||||
*it = 0;
|
||||
--it;
|
||||
}
|
||||
// reached end
|
||||
if(it < addr.begin())
|
||||
return true;
|
||||
(*it)++;
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool decrement_buffer(T &addr) {
|
||||
typename T::iterator it = addr.end() - 1;
|
||||
while(it >= addr.begin() && *it == 0) {
|
||||
*it = 0xff;
|
||||
--it;
|
||||
}
|
||||
// reached end
|
||||
if(it < addr.begin())
|
||||
return true;
|
||||
(*it)--;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool increment(IPv4Address &addr);
|
||||
bool increment(IPv6Address &addr);
|
||||
bool decrement(IPv4Address &addr);
|
||||
bool decrement(IPv6Address &addr);
|
||||
template<size_t n>
|
||||
bool increment(HWAddress<n> &addr) {
|
||||
return increment_buffer(addr);
|
||||
}
|
||||
template<size_t n>
|
||||
bool decrement(HWAddress<n> &addr) {
|
||||
return decrement_buffer(addr);
|
||||
}
|
||||
|
||||
IPv4Address last_address_from_mask(IPv4Address addr, IPv4Address mask);
|
||||
IPv6Address last_address_from_mask(IPv6Address addr, const IPv6Address &mask);
|
||||
template<size_t n>
|
||||
HWAddress<n> last_address_from_mask(HWAddress<n> addr, const HWAddress<n> &mask) {
|
||||
typename HWAddress<n>::iterator addr_iter = addr.begin();
|
||||
for(typename HWAddress<n>::const_iterator it = mask.begin(); it != mask.end(); ++it, ++addr_iter) {
|
||||
*addr_iter = *addr_iter | ~*it;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
inline bool is_dot3(const uint8_t *ptr, size_t sz) {
|
||||
return (sz >= 13 && ptr[12] < 8);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct is_unsigned_integral {
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is_unsigned_integral<uint8_t> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is_unsigned_integral<uint16_t> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is_unsigned_integral<uint32_t> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct is_unsigned_integral<uint64_t> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
#if TINS_IS_CXX11
|
||||
|
||||
// Part of C++14 standard library
|
||||
template<bool B, class T = void>
|
||||
using enable_if_t = typename std::enable_if<B,T>::type;
|
||||
|
||||
// Template metaprogramming trait to determine if a functor can accept another parameter as an argument
|
||||
template <class T, class P, class=void>
|
||||
struct accepts_type : std::false_type { };
|
||||
|
||||
template <class T, class P>
|
||||
struct accepts_type<T, P, enable_if_t<
|
||||
std::is_same< decltype( std::declval<T>()(std::declval<P>()) ), bool>::value
|
||||
>> : std::true_type { };
|
||||
|
||||
// use enable_if to invoke the Packet&& version of the sniff_loop handler if possible - otherwise fail to old behavior
|
||||
template <class Functor, class Packet>
|
||||
bool invoke_loop_cb(Functor& f, Packet& p, typename std::enable_if<accepts_type<Functor, Packet>::value, bool>::type* = 0) {
|
||||
return f(std::move(p));
|
||||
}
|
||||
|
||||
template <class Functor, class Packet>
|
||||
bool invoke_loop_cb(Functor& f, Packet& p, typename std::enable_if<!accepts_type<Functor, Packet>::value && accepts_type<Functor, Packet&>::value, bool>::type* = 0) {
|
||||
return f(p);
|
||||
}
|
||||
|
||||
template <class Functor, class Packet>
|
||||
bool invoke_loop_cb(Functor& f, Packet& p, typename std::enable_if<!accepts_type<Functor, Packet>::value && !accepts_type<Functor, Packet&>::value, bool>::type* = 0) {
|
||||
return f(*p.pdu());
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace Internals
|
||||
} // namespace Tins
|
||||
/**
|
||||
* \endcond
|
||||
*/
|
||||
#include <tins/detail/type_traits.h>
|
||||
#include <tins/detail/address_helpers.h>
|
||||
#include <tins/detail/icmp_extension_helpers.h>
|
||||
#include <tins/detail/smart_ptr.h>
|
||||
#include <tins/detail/pdu_helpers.h>
|
||||
#include <tins/detail/sequence_number_helpers.h>
|
||||
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user