Compare commits
720 Commits
STABLE-1_3
...
STABLE-1_4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b8b5d459e | ||
|
|
6d8dee6d68 | ||
|
|
3db149b42e | ||
|
|
03fb581252 | ||
|
|
5e224aba6d | ||
|
|
6b3179fbbf | ||
|
|
d0a25c2574 | ||
|
|
45e142af55 | ||
|
|
3eccdf65aa | ||
|
|
2b9933eb1e | ||
|
|
fe7bbae8a7 | ||
|
|
d77b354377 | ||
|
|
ca30f4b02e | ||
|
|
21a1cf9c80 | ||
|
|
6486c4b1d7 | ||
|
|
5deeaa652a | ||
|
|
3db3811054 | ||
|
|
f8bafcb298 | ||
|
|
eb658da462 | ||
|
|
d8b2bc2788 | ||
|
|
07af231f2b | ||
|
|
8d04da8c6e | ||
|
|
6b37e7ec74 | ||
|
|
8c5edcf564 | ||
|
|
162432fe24 | ||
|
|
13791ccff3 | ||
|
|
aecc5db1be | ||
|
|
d4b169a6de | ||
|
|
61588f9d90 | ||
|
|
63dbd8faed | ||
|
|
4d71f7270b | ||
|
|
593f75fc3b | ||
|
|
bec8cf9f38 | ||
|
|
b163197340 | ||
|
|
be1dccd15e | ||
|
|
83b46811f9 | ||
|
|
1d96195f47 | ||
|
|
5546e46c60 | ||
|
|
4bcb7accb8 | ||
|
|
5f4f07c193 | ||
|
|
f76488a841 | ||
|
|
ef0a44c62d | ||
|
|
d3ee77e7b1 | ||
|
|
a91d8e7395 | ||
|
|
8114627d6a | ||
|
|
3306641708 | ||
|
|
1ebd914cdc | ||
|
|
56207f2505 | ||
|
|
4c8e4fa003 | ||
|
|
c4f3b8818a | ||
|
|
f0b0a3760c | ||
|
|
b361533584 | ||
|
|
40a16289f7 | ||
|
|
ec565c8a19 | ||
|
|
0b382a0d53 | ||
|
|
386a4b7079 | ||
|
|
3585cc1a70 | ||
|
|
4790ebf282 | ||
|
|
4ffbcbf62e | ||
|
|
76e74b6635 | ||
|
|
77f0305ef0 | ||
|
|
935144b3a3 | ||
|
|
a148e33c42 | ||
|
|
d96703bba3 | ||
|
|
9621ccb712 | ||
|
|
21f39082b7 | ||
|
|
0da2bd7f62 | ||
|
|
d8f090a759 | ||
|
|
bd0a664446 | ||
|
|
aafa00f3aa | ||
|
|
dbbd161219 | ||
|
|
26f69123fd | ||
|
|
de4a51e96e | ||
|
|
a0bd27053d | ||
|
|
56cee6b4d8 | ||
|
|
277c7aa518 | ||
|
|
5cfef5bf48 | ||
|
|
ca6fd6015c | ||
|
|
eff10f6458 | ||
|
|
9c3a6b828f | ||
|
|
ba3567ea40 | ||
|
|
513522d7c4 | ||
|
|
5715469d26 | ||
|
|
140eb22cf0 | ||
|
|
ac7c061406 | ||
|
|
45a3f198e8 | ||
|
|
d5eb52868e | ||
|
|
3d48abb98d | ||
|
|
223307fa38 | ||
|
|
c951ab8cee | ||
|
|
81a49a437a | ||
|
|
5460900b14 | ||
|
|
2576a2e565 | ||
|
|
49369cc9ce | ||
|
|
fe66fa6540 | ||
|
|
72e2d16f14 | ||
|
|
378bed8a03 | ||
|
|
9a1eeeea67 | ||
|
|
68f8966f74 | ||
|
|
e6a179ea32 | ||
|
|
adb2aeb10f | ||
|
|
a030b741a5 | ||
|
|
6145af516b | ||
|
|
b1359f1c80 | ||
|
|
7d254a542c | ||
|
|
422e7963de | ||
|
|
e2cdf0d39d | ||
|
|
2fe1af0d05 | ||
|
|
ff85feb22d | ||
|
|
be191148e0 | ||
|
|
626131fb28 | ||
|
|
d154f5c653 | ||
|
|
38f619dd6f | ||
|
|
5b899dd85b | ||
|
|
e7b9849a1a | ||
|
|
b1980b36b8 | ||
|
|
20833fdcc4 | ||
|
|
1ac0c90ec4 | ||
|
|
e931086c3e | ||
|
|
b65af6c572 | ||
|
|
5983c1c5ff | ||
|
|
be412dc042 | ||
|
|
23dfcf7b8c | ||
|
|
e8b80b8ae9 | ||
|
|
a7f7762302 | ||
|
|
859fd87600 | ||
|
|
211b8be07d | ||
|
|
22ee104a04 | ||
|
|
5048a30fc7 | ||
|
|
49e16fcbe9 | ||
|
|
1b79ac1160 | ||
|
|
f9e286ff67 | ||
|
|
d798abcb91 | ||
|
|
5c05d427b0 | ||
|
|
a45b1bad35 | ||
|
|
88bf9b2380 | ||
|
|
717b2dab59 | ||
|
|
8d74559f72 | ||
|
|
59513b41e5 | ||
|
|
fe2003124a | ||
|
|
8b06c61a70 | ||
|
|
ce6fb83ef4 | ||
|
|
85f8a59d7f | ||
|
|
dd8729063c | ||
|
|
14c766e750 | ||
|
|
988815579a | ||
|
|
08b497faea | ||
|
|
96d332e234 | ||
|
|
440f31a4d3 | ||
|
|
cb91705e03 | ||
|
|
d12e742373 | ||
|
|
7aa7c0f481 | ||
|
|
b3ffa16315 | ||
|
|
09d1f55bce | ||
|
|
21333d0f18 | ||
|
|
edcc859b58 | ||
|
|
2ce17a724a | ||
|
|
0fb07ba328 | ||
|
|
78f0307246 | ||
|
|
c5203ab5ea | ||
|
|
3d1a306518 | ||
|
|
2750d61e92 | ||
|
|
43ac5ad70d | ||
|
|
309e936ad9 | ||
|
|
d00fa906cf | ||
|
|
01839b9c14 | ||
|
|
1f396946e5 | ||
|
|
2f58ef781c | ||
|
|
8b9f70ac08 | ||
|
|
e039d4103f | ||
|
|
0333e81616 | ||
|
|
cf1be4ae2d | ||
|
|
dc34636598 | ||
|
|
c74d881d3d | ||
|
|
ab51f3bec0 | ||
|
|
b4c4fae3f5 | ||
|
|
ce98df59f1 | ||
|
|
f29bdd21a7 | ||
|
|
9d31401d47 | ||
|
|
5c68bbe16f | ||
|
|
07c610e068 | ||
|
|
998f109fc8 | ||
|
|
cfb70bccc1 | ||
|
|
7524f9006e | ||
|
|
bcfe3dacc6 | ||
|
|
6c56151d27 | ||
|
|
98274d2145 | ||
|
|
1d125f55ba | ||
|
|
918470affc | ||
|
|
797f26e45b | ||
|
|
e145c1d31c | ||
|
|
bb5d0c5c4a | ||
|
|
0aea1b608a | ||
|
|
a2aa43a426 | ||
|
|
8d5514603e | ||
|
|
b9a2feff5e | ||
|
|
f13615d97a | ||
|
|
d6227aece6 | ||
|
|
6058389974 | ||
|
|
dccad08508 | ||
|
|
112158b056 | ||
|
|
5be300736e | ||
|
|
1b98a64e90 | ||
|
|
4849eb4c54 | ||
|
|
5e8ee7e006 | ||
|
|
e27d34d118 | ||
|
|
a0bf8d5740 | ||
|
|
17a5ba08e4 | ||
|
|
d0877153bf | ||
|
|
55011e5308 | ||
|
|
2697b3c7da | ||
|
|
b9c17dd1f0 | ||
|
|
aea17bfae2 | ||
|
|
0a5755145c | ||
|
|
249e19769b | ||
|
|
f64808c385 | ||
|
|
2e69b54a4f | ||
|
|
cd5d1ceadf | ||
|
|
c55f6b40ec | ||
|
|
bf4ec9be22 | ||
|
|
ed0626afeb | ||
|
|
b5305d5a8c | ||
|
|
17efa04ea6 | ||
|
|
b3f5c8f6b2 | ||
|
|
4507083148 | ||
|
|
f4c0018d7a | ||
|
|
c9e1d6cca8 | ||
|
|
242dc34115 | ||
|
|
41c785d77a | ||
|
|
a745528b40 | ||
|
|
7465be91d0 | ||
|
|
d79c5baa1b | ||
|
|
46af0d38fa | ||
|
|
6323e09a0a | ||
|
|
d94bdb75c8 | ||
|
|
cc3b4dff20 | ||
|
|
78ac382fdf | ||
|
|
860072aaaf | ||
|
|
2694a409c6 | ||
|
|
206b1f4631 | ||
|
|
ef9891e8ff | ||
|
|
bd69890ccd | ||
|
|
fc280c7cd6 | ||
|
|
435ac2a650 | ||
|
|
fb0ad2f9ea | ||
|
|
7385449f33 | ||
|
|
1f4b814d0b | ||
|
|
a93d9c4310 | ||
|
|
1813d11b9d | ||
|
|
09ac68c196 | ||
|
|
c2fd905e32 | ||
|
|
cc84f28d1b | ||
|
|
2bd498524d | ||
|
|
4b934945f3 | ||
|
|
b666ab0673 | ||
|
|
6a4c30fe5d | ||
|
|
4002aef594 | ||
|
|
ba28d36e67 | ||
|
|
4444db2990 | ||
|
|
d0026793bf | ||
|
|
93b5cd5ddd | ||
|
|
12c2d7e4cf | ||
|
|
4eb5acd9e2 | ||
|
|
0f56d838ec | ||
|
|
12a948dacb | ||
|
|
137953605e | ||
|
|
629fad6f5f | ||
|
|
2911c84a69 | ||
|
|
89a1420609 | ||
|
|
e584557afe | ||
|
|
2ed5413e24 | ||
|
|
91532b2d5c | ||
|
|
732cac1c0e | ||
|
|
5b04860b8b | ||
|
|
5a674f419d | ||
|
|
d30246dc05 | ||
|
|
af5a913019 | ||
|
|
604e69c7ae | ||
|
|
d765c9de37 | ||
|
|
98b6e2bcce | ||
|
|
d80be7961c | ||
|
|
2aec3a9789 | ||
|
|
ccd7dbe0e4 | ||
|
|
92fcfd7a6f | ||
|
|
1b2b054139 | ||
|
|
853d1eac96 | ||
|
|
2ef29d6839 | ||
|
|
6865806b55 | ||
|
|
9546e65617 | ||
|
|
5852993243 | ||
|
|
90a03a77ad | ||
|
|
4bfbe7ebeb | ||
|
|
f3c1686a40 | ||
|
|
33a587d97e | ||
|
|
a444ec5111 | ||
|
|
5ead1bf5c8 | ||
|
|
3a267586f4 | ||
|
|
52271e0366 | ||
|
|
e4739da961 | ||
|
|
80b344e9fc | ||
|
|
036cb26fa3 | ||
|
|
33d6dcec5b | ||
|
|
791505ab6e | ||
|
|
88e1719d8e | ||
|
|
0885555521 | ||
|
|
36c1750b8f | ||
|
|
11b1c9f19f | ||
|
|
b5dd87b184 | ||
|
|
b54c7bedfd | ||
|
|
783404d8d4 | ||
|
|
3bad9f013e | ||
|
|
4495516497 | ||
|
|
3f849848a4 | ||
|
|
7203680146 | ||
|
|
d793ed3b9b | ||
|
|
c6de17d1e5 | ||
|
|
5b084f4b95 | ||
|
|
4e3b2b9f6b | ||
|
|
856ccb5bb7 | ||
|
|
dbf5659cd9 | ||
|
|
fee0c6afe9 | ||
|
|
fb7d3a159a | ||
|
|
dc6b4e65e0 | ||
|
|
17d4ef4053 | ||
|
|
03be8f88fe | ||
|
|
effcb90fdf | ||
|
|
1bd06bee82 | ||
|
|
92cdc1e33f | ||
|
|
377628216e | ||
|
|
f7627929d5 | ||
|
|
b49cf5e7a2 | ||
|
|
231a6cecb4 | ||
|
|
32f02325f9 | ||
|
|
f418782c2c | ||
|
|
e52730d1fb | ||
|
|
d2679e58a6 | ||
|
|
e3817cd549 | ||
|
|
4ace50a7d7 | ||
|
|
fa092c47c8 | ||
|
|
704d90f693 | ||
|
|
93dc36e091 | ||
|
|
4cc36b2284 | ||
|
|
aaa8d2795e | ||
|
|
229137cad1 | ||
|
|
d73262a0e5 | ||
|
|
cd22a8d851 | ||
|
|
7f7df4ae19 | ||
|
|
3c5723e49d | ||
|
|
960fb14bf5 | ||
|
|
21e17f649a | ||
|
|
9782c40d21 | ||
|
|
04beab4f7d | ||
|
|
194a85387b | ||
|
|
a99219ad1f | ||
|
|
691410ba18 | ||
|
|
714a43b18c | ||
|
|
9f457d3331 | ||
|
|
60a456f757 | ||
|
|
2b355d6b34 | ||
|
|
48be546357 | ||
|
|
0f74a57267 | ||
|
|
272270c7f4 | ||
|
|
e2f014f457 | ||
|
|
1fba33628d | ||
|
|
7d604a23f0 | ||
|
|
6929a786aa | ||
|
|
f61b80ca6a | ||
|
|
1aba9f031d | ||
|
|
2ffcc52f03 | ||
|
|
72518a0d6e | ||
|
|
1242575f0f | ||
|
|
6ccc2ef804 | ||
|
|
b3dc6f2b5b | ||
|
|
2427917db8 | ||
|
|
5ab40f016d | ||
|
|
435115d4fb | ||
|
|
24d823dae6 | ||
|
|
2c60a48d02 | ||
|
|
4b0be4a477 | ||
|
|
505dd10d3c | ||
|
|
ddd2b69f27 | ||
|
|
66b57f89df | ||
|
|
69bd5a29d9 | ||
|
|
f7479781c1 | ||
|
|
9bfeb4e5af | ||
|
|
d3e5ade2da | ||
|
|
3833dd86aa | ||
|
|
25f33c8444 | ||
|
|
dae247809b | ||
|
|
81df8bdabd | ||
|
|
03e4eb4de8 | ||
|
|
290bd400c3 | ||
|
|
5d0785e47a | ||
|
|
16434568b0 | ||
|
|
c0e7d54e37 | ||
|
|
ccb53d9e7d | ||
|
|
03bd61c799 | ||
|
|
6ffd29507c | ||
|
|
a880709776 | ||
|
|
874d1641df | ||
|
|
d8d964d09e | ||
|
|
46b3cb580d | ||
|
|
02f5e19420 | ||
|
|
a945bf07af | ||
|
|
7e5b0a9eb6 | ||
|
|
a56795c149 | ||
|
|
baeb41f5f4 | ||
|
|
d0348e0c60 | ||
|
|
ef0a7ecbcd | ||
|
|
778c65d27c | ||
|
|
f3face9f0c | ||
|
|
2edd5230c9 | ||
|
|
1551bb702d | ||
|
|
d656e9f28e | ||
|
|
597764e35b | ||
|
|
f9f77876a1 | ||
|
|
67d8c7999a | ||
|
|
a7fdb67e8f | ||
|
|
4d1ff2418e | ||
|
|
71f5fdef42 | ||
|
|
abc36471d9 | ||
|
|
4b7288e8f4 | ||
|
|
108ed3c81a | ||
|
|
f98e5717e5 | ||
|
|
3685bc4828 | ||
|
|
72c580236e | ||
|
|
01d2a87f5d | ||
|
|
51061fb61e | ||
|
|
49e8e28cf6 | ||
|
|
d2c632fb18 | ||
|
|
3562be2188 | ||
|
|
2e18a9be63 | ||
|
|
3347762df3 | ||
|
|
f1bc73c3ed | ||
|
|
a96fa7d221 | ||
|
|
cc3e01a9f5 | ||
|
|
6caa389c48 | ||
|
|
e86446b785 | ||
|
|
a00448c35a | ||
|
|
82b9152b8d | ||
|
|
d778fbb24f | ||
|
|
3803a0021d | ||
|
|
3c96819a2c | ||
|
|
846a2fb933 | ||
|
|
7e9eb55350 | ||
|
|
46b7bd6ec3 | ||
|
|
8bbe3d2fe0 | ||
|
|
25f59761b3 | ||
|
|
4b038f13de | ||
|
|
da3d84d1dc | ||
|
|
5ef976aed5 | ||
|
|
cf0b831971 | ||
|
|
d861daeb4e | ||
|
|
0a2eb3fdc8 | ||
|
|
6fb248c9e0 | ||
|
|
40946a79d3 | ||
|
|
124ca0fed2 | ||
|
|
5d153ca1b3 | ||
|
|
a5b0ea97d6 | ||
|
|
0a49f2e068 | ||
|
|
57594ad7b6 | ||
|
|
75bb43698c | ||
|
|
f70014b8ea | ||
|
|
5fd410db4b | ||
|
|
385d044f7d | ||
|
|
d0f1c552e2 | ||
|
|
a54bb7205d | ||
|
|
7466474365 | ||
|
|
c4bc9ce59a | ||
|
|
e25c9f7951 | ||
|
|
94cbed5096 | ||
|
|
f83ace2034 | ||
|
|
84ed9de21a | ||
|
|
4e764017c1 | ||
|
|
67f5e17588 | ||
|
|
d13ac66cc4 | ||
|
|
9f0b7261e5 | ||
|
|
ad4a869b94 | ||
|
|
79d3b41e13 | ||
|
|
839befe68a | ||
|
|
097e8c8eb4 | ||
|
|
90c7d3aaff | ||
|
|
2621e3fa19 | ||
|
|
36d7f50d77 | ||
|
|
ffbb582dde | ||
|
|
3bfc07eb92 | ||
|
|
d91caf1cd3 | ||
|
|
2a2be49d2c | ||
|
|
d47a04456b | ||
|
|
b9499d07c2 | ||
|
|
5d20e690fd | ||
|
|
1c23bfdc7f | ||
|
|
d5531a239b | ||
|
|
9e37d70163 | ||
|
|
99ff7efe80 | ||
|
|
43a08bef14 | ||
|
|
92beddd72f | ||
|
|
f5b783d107 | ||
|
|
a5a870c683 | ||
|
|
19ab25c861 | ||
|
|
38fcfcdfac | ||
|
|
957f4d8096 | ||
|
|
5d4438e652 | ||
|
|
4649c14856 | ||
|
|
fcf6434b4b | ||
|
|
464950d51e | ||
|
|
0b5d60db5e | ||
|
|
b6542b977e | ||
|
|
2bf1184c39 | ||
|
|
103b5a760f | ||
|
|
2b1c389955 | ||
|
|
8d9fa63460 | ||
|
|
52b87b751f | ||
|
|
e934f8aac6 | ||
|
|
311d16df7d | ||
|
|
ea78d69c6d | ||
|
|
402597c2cb | ||
|
|
68678e21df | ||
|
|
19a9b52c06 | ||
|
|
db38ee6630 | ||
|
|
1d8538bca4 | ||
|
|
b73dcfb8cf | ||
|
|
bcd4b76d31 | ||
|
|
7c57ee0c17 | ||
|
|
d9157a71bb | ||
|
|
eae9798276 | ||
|
|
e131d3e32a | ||
|
|
36043a92e7 | ||
|
|
9b48657444 | ||
|
|
52970c2459 | ||
|
|
8336796c1a | ||
|
|
16a63c6554 | ||
|
|
c637441f52 | ||
|
|
5b221ecd4f | ||
|
|
7af77aefa7 | ||
|
|
7c2054091d | ||
|
|
e04e0cb98e | ||
|
|
e983865ad5 | ||
|
|
4c9fe60693 | ||
|
|
c5dfa4099d | ||
|
|
524b7bc36b | ||
|
|
8908055b63 | ||
|
|
10abe8aba2 | ||
|
|
7b24a6360c | ||
|
|
96e9689dbd | ||
|
|
7e0204bb7b | ||
|
|
dfb80c6b86 | ||
|
|
838c35acf6 | ||
|
|
c858aa5686 | ||
|
|
b1736b13d7 | ||
|
|
cbb86fe590 | ||
|
|
a61f5f3a78 | ||
|
|
0792effc2a | ||
|
|
49c6ce3703 | ||
|
|
0f05a6aede | ||
|
|
7ccf8cb731 | ||
|
|
7c28c66d32 | ||
|
|
c49a3ab2d6 | ||
|
|
8fbaf0304a | ||
|
|
f89c08872c | ||
|
|
29eb56a2f6 | ||
|
|
2e795d2706 | ||
|
|
8768e4488a | ||
|
|
bd3f86e505 | ||
|
|
82e4716784 | ||
|
|
d3635c5eef | ||
|
|
c73b1b4fa2 | ||
|
|
39df7d048c | ||
|
|
3529349470 | ||
|
|
0030d1ade5 | ||
|
|
2d1631792a | ||
|
|
b6babe38ea | ||
|
|
df7e435b86 | ||
|
|
9e59f661bc | ||
|
|
87c2d911c9 | ||
|
|
44af02aa1e | ||
|
|
45e51d1929 | ||
|
|
59a623e648 | ||
|
|
306f2203fa | ||
|
|
7699b59e27 | ||
|
|
1550c4215d | ||
|
|
a84590273d | ||
|
|
6fe258c6bc | ||
|
|
27c1c7a0f7 | ||
|
|
a668a4e4d1 | ||
|
|
b1250f003d | ||
|
|
3f8e6c423c | ||
|
|
077caac76d | ||
|
|
91d70a3364 | ||
|
|
6af20340dd | ||
|
|
68ab197b68 | ||
|
|
79e6b4c819 | ||
|
|
ececc3ca45 | ||
|
|
630f575017 | ||
|
|
49274c1507 | ||
|
|
27d4cf6aef | ||
|
|
b156d392cb | ||
|
|
b0b4290c29 | ||
|
|
90bed0c5ac | ||
|
|
b3caddab30 | ||
|
|
1017279e68 | ||
|
|
f74cebcbcd | ||
|
|
848debf999 | ||
|
|
47756a8faa | ||
|
|
6c027c153b | ||
|
|
28dc5f491c | ||
|
|
758e99f362 | ||
|
|
010dc6258e | ||
|
|
a5c5949009 | ||
|
|
d51d6b2d89 | ||
|
|
c58dfa2156 | ||
|
|
5d360a6711 | ||
|
|
24fcf9a86e | ||
|
|
a23b446ddf | ||
|
|
258fe88232 | ||
|
|
9ff7d29696 | ||
|
|
30d69d68e3 | ||
|
|
4495d9ef5b | ||
|
|
a66039b86c | ||
|
|
81c5d9e983 | ||
|
|
c6f7a34abe | ||
|
|
72d6f1a418 | ||
|
|
8cb3ea1398 | ||
|
|
8712deb0b2 | ||
|
|
2e8de4f601 | ||
|
|
c22d3b4c98 | ||
|
|
f8c22c7428 | ||
|
|
855dcadf7a | ||
|
|
9c41e1eea3 | ||
|
|
c70c3eac62 | ||
|
|
e58f4c567a | ||
|
|
1dd8300e69 | ||
|
|
5fa0347e64 | ||
|
|
32c16fad42 | ||
|
|
ea3b8f52d5 | ||
|
|
95445fc328 | ||
|
|
21e3cde95c | ||
|
|
d587940801 | ||
|
|
f5d4f3d83c | ||
|
|
04a8b0f85d | ||
|
|
853e33bdb4 | ||
|
|
0644c4c08e | ||
|
|
606fed8896 | ||
|
|
a5463f0400 | ||
|
|
96338314f1 | ||
|
|
5d3cab0042 | ||
|
|
e678e1bdcb | ||
|
|
1811a344f5 | ||
|
|
ef31aa12e2 | ||
|
|
9dd6c28523 | ||
|
|
61e5301d49 | ||
|
|
408829bcf6 | ||
|
|
dbcce3a4be | ||
|
|
426dd9bfad | ||
|
|
82318c0ef1 | ||
|
|
60696a8485 | ||
|
|
7044385d8e | ||
|
|
a7139ef06b | ||
|
|
52389fc09a | ||
|
|
972ca9e6c1 | ||
|
|
e0c5c4de88 | ||
|
|
149f21dc58 | ||
|
|
9632632b85 | ||
|
|
cc1e9370af | ||
|
|
34139606ca | ||
|
|
3e1cca65bd | ||
|
|
0e3c256667 | ||
|
|
618355f5a7 | ||
|
|
ca11baf1cd | ||
|
|
7ede02ca8b | ||
|
|
2d4e76874c | ||
|
|
b463562241 | ||
|
|
04f17c4709 | ||
|
|
97f797e859 | ||
|
|
9521f54741 | ||
|
|
0e38a52edc | ||
|
|
6df94d3c76 | ||
|
|
59005b544f | ||
|
|
8596bb7e7e | ||
|
|
1c47d15577 | ||
|
|
67c587f9f7 | ||
|
|
052be0a328 | ||
|
|
68ddcc6ca7 | ||
|
|
9a2d97ec41 | ||
|
|
47e770dffa | ||
|
|
8292cebfd9 | ||
|
|
c483c13dc4 | ||
|
|
86f2942c2a | ||
|
|
e4d19dc4a0 | ||
|
|
763760503b | ||
|
|
13c9d2dade | ||
|
|
97f6c5b239 | ||
|
|
f4a9d173a1 | ||
|
|
d85a18752f | ||
|
|
aa7dd9a8ad | ||
|
|
27c9670718 | ||
|
|
32833bcd56 | ||
|
|
53bc34f3e2 | ||
|
|
81640c4a83 | ||
|
|
533e6b5f8d | ||
|
|
28f0bbd575 | ||
|
|
39717b2d9d | ||
|
|
79c88cdcfd | ||
|
|
8a34c16aee | ||
|
|
cce192a671 | ||
|
|
cfe4a12a46 | ||
|
|
3269da52cc | ||
|
|
9c51487d1a | ||
|
|
3ba5ddefa7 | ||
|
|
1d45aa8d45 | ||
|
|
a7bcdf4398 | ||
|
|
9a0dac5885 | ||
|
|
c9e0652526 | ||
|
|
a566f9d8f2 | ||
|
|
1740b0d421 | ||
|
|
802a048302 | ||
|
|
fa08823ac4 | ||
|
|
a1c0b9da7b | ||
|
|
bf261f4f13 | ||
|
|
dc8639bc06 |
946
CHANGELOG
946
CHANGELOG
@@ -1,27 +1,947 @@
|
||||
FUTURE
|
||||
|
||||
* TODO: The lwIP source code makes some invalid assumptions on processor
|
||||
word-length, storage sizes and alignment. See the mailing lists for
|
||||
problems with exoteric (/DSP) architectures showing these problems.
|
||||
We still have to fix some of these issues neatly.
|
||||
|
||||
* TODO: the PPP code is broken in a few ways. There are namespace
|
||||
collisions on BSD systems and many assumptions on word-length
|
||||
(sizeof(int)). In ppp.c an assumption is made on the availability of
|
||||
a thread subsystem. Either PPP needs to be moved to contrib/ports/???
|
||||
or rearranged to be more generic.
|
||||
|
||||
HISTORY
|
||||
|
||||
(CVS HEAD)
|
||||
|
||||
* [Enter new changes just after this line - do not remove this line]
|
||||
|
||||
++ New features:
|
||||
|
||||
2012-03-25: Simon Goldschmidt (idea by Mason)
|
||||
* posix/*: added posix-compatibility include files posix/netdb.h and posix/sys/socket.h
|
||||
which are a simple wrapper to the correct lwIP include files.
|
||||
|
||||
2012-01-16: Simon Goldschmidt
|
||||
* opt.h, icmp.c: Added option CHECKSUM_GEN_ICMP
|
||||
|
||||
2011-12-17: Simon Goldschmidt
|
||||
* ip.h: implemented API functions to access so_options of IP pcbs (UDP, TCP, RAW)
|
||||
(fixes bug #35061)
|
||||
|
||||
2011-09-27: Simon Goldschmidt
|
||||
* opt.h, tcp.c, tcp_in.c: Implemented limiting data on ooseq queue (task #9989)
|
||||
(define TCP_OOSEQ_MAX_BYTES / TCP_OOSEQ_MAX_PBUFS in lwipopts.h)
|
||||
|
||||
2011-09-21: Simon Goldschmidt
|
||||
* opt.h, api.h, api_lib.c, api_msg.h/.c, sockets.c: Implemented timeout on
|
||||
send (TCP only, bug #33820)
|
||||
|
||||
2011-09-21: Simon Goldschmidt
|
||||
* init.c: Converted runtime-sanity-checks into compile-time checks that can
|
||||
be disabled (since runtime checks can often not be seen on embedded targets)
|
||||
|
||||
2011-09-11: Simon Goldschmidt
|
||||
* ppp.h, ppp_impl.h: splitted ppp.h to an internal and external header file
|
||||
to get a clear separation of which functions an application or port may use
|
||||
(task #11281)
|
||||
|
||||
2011-09-11: Simon Goldschmidt
|
||||
* opt.h, tcp_impl.h, tcp.c, udp.h/.c: Added a config option to randomize
|
||||
initial local TCP/UDP ports (so that different port ranges are used after
|
||||
a reboot; bug #33818; this one added tcp_init/udp_init functions again)
|
||||
|
||||
2011-09-03: Simon Goldschmidt
|
||||
* dhcp.c: DHCP uses LWIP_RAND() for xid's (bug #30302)
|
||||
|
||||
2011-08-24: Simon Goldschmidt
|
||||
* opt.h, netif.h/.c: added netif remove callback (bug #32397)
|
||||
|
||||
2011-07-26: Simon Goldschmidt
|
||||
* etharp.c: ETHARP_SUPPORT_VLAN: add support for an external VLAN filter
|
||||
function instead of only checking for one VLAN (define ETHARP_VLAN_CHECK_FN)
|
||||
|
||||
2011-07-21: Simon Goldschmidt (patch by hanhui)
|
||||
* ip4.c, etharp.c, pbuf.h: bug #33634 ip_forward() have a faulty behaviour:
|
||||
Added pbuf flags to mark incoming packets as link-layer broadcast/multicast.
|
||||
Also added code to allow ip_forward() to forward non-broadcast packets to
|
||||
the input netif (set IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1).
|
||||
|
||||
2011-06-26: Simon Goldschmidt (patch by Cameron Gutman)
|
||||
* tcp.c, tcp_out.c: bug #33604: added some more asserts to check that
|
||||
pcb->state != LISTEN
|
||||
|
||||
2011-05-14: Simon Goldschmidt (patch by St<53>phane Lesage)
|
||||
* tcpip.c/.h: patch #7449 allow tcpip callback from interrupt with static
|
||||
memory message
|
||||
|
||||
|
||||
++ Bugfixes:
|
||||
|
||||
2012-09-26: Simon Goldschmidt
|
||||
* api_msg.c: fixed bug #37405 'err_tcp()' uses already freed 'netconn' object
|
||||
|
||||
2012-09-26: patch by Henrik Persson
|
||||
* dhcp.c: patch #7843 Fix corner case with dhcp timeouts
|
||||
|
||||
2012-09-26: patch by Henrik Persson
|
||||
* dhcp.c: patch #7840 Segfault in dhcp_parse_reply if no end marker in dhcp packet
|
||||
|
||||
2012-08-22: Simon Goldschmidt
|
||||
* memp.c: fixed bug #37166: memp_sanity check loops itself
|
||||
|
||||
2012-05-08: Simon Goldschmidt
|
||||
* tcp_out.c: fixed bug: #36380 unsent_oversize mismatch in 1.4.1RC1 (this was
|
||||
a debug-check issue only)
|
||||
|
||||
2012-03-27: Simon Goldschmidt
|
||||
* vj.c: fixed bug #35756 header length calculation problem in ppp/vj.c
|
||||
|
||||
2012-03-27: Simon Goldschmidt (patch by Mason)
|
||||
* tcp_out.c: fixed bug #35945: SYN packet should provide the recv MSS not the
|
||||
send MSS
|
||||
|
||||
2012-03-22: Simon Goldschmidt
|
||||
* ip4.c: fixed bug #35927: missing refragmentaion in ip_forward
|
||||
|
||||
2012-03-20: Simon Goldschmidt (patch by Mason)
|
||||
* netdb.c: fixed bug #35907: lwip_gethostbyname_r returns an invalid h_addr_list
|
||||
|
||||
2012-03-12: Simon Goldschmidt (patch by Bostjan Meglic)
|
||||
* ppp.c: fixed bug #35809: PPP GetMask(): Compiler warning on big endian,
|
||||
possible bug on little endian system
|
||||
|
||||
2012-02-23: Simon Goldschmidt
|
||||
* etharp.c: fixed bug #35595: Impossible to send broadcast without a gateway
|
||||
(introduced when fixing bug# 33551)
|
||||
|
||||
2012-02-16: Simon Goldschmidt
|
||||
* ppp.c: fixed pbuf leak when PPP session is aborted through pppSigHUP()
|
||||
(bug #35541: PPP Memory Leak)
|
||||
|
||||
2012-02-16: Simon Goldschmidt
|
||||
* etharp.c: fixed bug #35531: Impossible to send multicast without a gateway
|
||||
(introduced when fixing bug# 33551)
|
||||
|
||||
2012-02-16: Simon Goldschmidt (patch by St<53>phane Lesage)
|
||||
* msg_in.c, msg_out.c: fixed bug #35536 SNMP: error too big response is malformed
|
||||
|
||||
2012-02-15: Simon Goldschmidt
|
||||
* init.c: fixed bug #35537: MEMP_NUM_* sanity checks should be disabled with
|
||||
MEMP_MEM_MALLOC==1
|
||||
|
||||
2012-02-12: Simon Goldschmidt
|
||||
* tcp.h, tcp_in.c, tcp_out.c: partly fixed bug #25882: TCP hangs on
|
||||
MSS > pcb->snd_wnd (by not creating segments bigger than half the window)
|
||||
|
||||
2012-02-11: Simon Goldschmidt
|
||||
* tcp.c: fixed bug #35435: No pcb state check before adding it to time-wait
|
||||
queue while closing
|
||||
|
||||
2012-01-22: Simon Goldschmidt
|
||||
* tcp.c, tcp_in.c: fixed bug #35305: pcb may be freed too early on shutdown(WR)
|
||||
|
||||
2012-01-21: Simon Goldschmidt
|
||||
* tcp.c: fixed bug #34636: FIN_WAIT_2 - Incorrect shutdown of TCP pcb
|
||||
|
||||
2012-01-20: Simon Goldschmidt
|
||||
* dhcp.c: fixed bug #35151: DHCP asserts on incoming option lengths
|
||||
|
||||
2012-01-20: Simon Goldschmidt
|
||||
* pbuf.c: fixed bug #35291: NULL pointer in pbuf_copy
|
||||
|
||||
2011-11-25: Simon Goldschmidt
|
||||
* tcp.h/.c, tcp_impl.h, tcp_in.c: fixed bug #31177: tcp timers can corrupt
|
||||
tcp_active_pcbs in some cases
|
||||
|
||||
2011-11-23: Simon Goldschmidt
|
||||
* sys.c: fixed bug #34884: sys_msleep() body needs to be surrounded with
|
||||
'#ifndef sys_msleep'
|
||||
|
||||
2011-11-22: Simon Goldschmidt
|
||||
* netif.c, etharp.h/.c: fixed bug #34684: Clear the arp table cache when
|
||||
netif is brought down
|
||||
|
||||
2011-10-28: Simon Goldschmidt
|
||||
* tcp_in.c: fixed bug #34638: Dead code in tcp_receive - pcb->dupacks
|
||||
|
||||
2011-10-23: Simon Goldschmidt
|
||||
* mem.c: fixed bug #34429: possible memory corruption with
|
||||
LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT set to 1
|
||||
|
||||
2011-10-18: Simon Goldschmidt
|
||||
* arch.h, netdb.c: fixed bug #34592: lwip_gethostbyname_r uses nonstandard
|
||||
error value
|
||||
|
||||
2011-10-18: Simon Goldschmidt
|
||||
* opt.h: fixed default values of TCP_SNDLOWAT and TCP_SNDQUEUELOWAT for small
|
||||
windows (bug #34176 select after non-blocking send times out)
|
||||
|
||||
2011-10-18: Simon Goldschmidt
|
||||
* tcp_impl.h, tcp_out.c: fixed bug #34587: TCP_BUILD_MSS_OPTION doesn't
|
||||
consider netif->mtu, causes slow network
|
||||
|
||||
2011-10-18: Simon Goldschmidt
|
||||
* sockets.c: fixed bug #34581 missing parentheses in udplite sockets code
|
||||
|
||||
2011-10-18: Simon Goldschmidt
|
||||
* sockets.h: fixed bug #34580 fcntl() is missing in LWIP_COMPAT_SOCKETS
|
||||
|
||||
2011-10-17: Simon Goldschmidt
|
||||
* api_msg.c: fixed bug #34569: shutdown(SHUT_WR) crashes netconn/socket api
|
||||
|
||||
2011-10-13: Simon Goldschmidt
|
||||
* tcp_in.c, tcp_out.c: fixed bug #34517 (persist timer is started although no
|
||||
zero window is received) by starting the persist timer when a zero window is
|
||||
received, not when we have more data queued for sending than fits into the
|
||||
window
|
||||
|
||||
2011-10-13: Simon Goldschmidt
|
||||
* def.h, timers.c: fixed bug #34541: LWIP_U32_DIFF is unnecessarily complex
|
||||
|
||||
2011-10-13: Simon Goldschmidt
|
||||
* sockets.c, api_lib.c: fixed bug #34540: compiler error when CORE_LOCKING is
|
||||
used and not all protocols are enabled
|
||||
|
||||
2011-10-12: Simon Goldschmidt
|
||||
* pbuf.c: fixed bug #34534: Error in sending fragmented IP if MEM_ALIGNMENT > 4
|
||||
|
||||
2011-10-09: Simon Goldschmidt
|
||||
* tcp_out.c: fixed bug #34426: tcp_zero_window_probe() transmits incorrect
|
||||
byte value when pcb->unacked != NULL
|
||||
|
||||
2011-10-09: Simon Goldschmidt
|
||||
* ip4.c: fixed bug #34447 LWIP_IP_ACCEPT_UDP_PORT(dst_port) wrong
|
||||
|
||||
2011-09-27: Simon Goldschmidt
|
||||
* tcp_in.c, tcp_out.c: Reset pcb->unsent_oversize in 2 more places...
|
||||
|
||||
2011-09-27: Simon Goldschmidt
|
||||
* tcp_in.c: fixed bug #28288: Data after FIN in oos queue
|
||||
|
||||
2011-09-27: Simon Goldschmidt
|
||||
* dhcp.c: fixed bug #34406 dhcp_option_hostname() can overflow the pbuf
|
||||
|
||||
2011-09-24: Simon Goldschmidt
|
||||
* mem.h: fixed bug #34377 MEM_SIZE_F is not defined if MEM_LIBC_MALLOC==1
|
||||
|
||||
2011-09-23: Simon Goldschmidt
|
||||
* pbuf.h, tcp.c, tcp_in.c: fixed bug #33871: rejecting TCP_EVENT_RECV() for
|
||||
the last packet including FIN can lose data
|
||||
|
||||
2011-09-22: Simon Goldschmidt
|
||||
* tcp_impl.h: fixed bug #34355: nagle does not take snd_buf/snd_queuelen into
|
||||
account
|
||||
|
||||
2011-09-21: Simon Goldschmidt
|
||||
* opt.h: fixed default value of TCP_SND_BUF to not violate the sanity checks
|
||||
in init.c
|
||||
|
||||
2011-09-20: Simon Goldschmidt
|
||||
* timers.c: fixed bug #34337 (possible NULL pointer in sys_check_timeouts)
|
||||
|
||||
2011-09-11: Simon Goldschmidt
|
||||
* tcp_out.c: use pcb->mss instead of TCP_MSS for preallocate mss-sized pbufs
|
||||
(bug #34019)
|
||||
|
||||
2011-09-09: Simon Goldschmidt
|
||||
* udp.c: fixed bug #34072: UDP broadcast is received from wrong UDP pcb if
|
||||
udp port matches
|
||||
|
||||
2011-09-03: Simon Goldschmidt
|
||||
* tcp_in.c: fixed bug #33952 PUSH flag in incoming packet is lost when packet
|
||||
is aggregated and sent to application
|
||||
|
||||
2011-09-01: Simon Goldschmidt
|
||||
* opt.h: fixed bug #31809 LWIP_EVENT_API in opts.h is inconsistent compared
|
||||
to other options
|
||||
|
||||
2011-09-01: Simon Goldschmidt
|
||||
* tcp_in.c: fixed bug #34111 RST for ACK to listening pcb has wrong seqno
|
||||
|
||||
2011-08-24: Simon Goldschmidt
|
||||
* api_msg.c, sockets.c: fixed bug #33956 Wrong error returned when calling
|
||||
accept() on UDP connections
|
||||
|
||||
2011-08-24: Simon Goldschmidt
|
||||
* sockets.h: fixed bug #34057 socklen_t should be a typedef
|
||||
|
||||
2011-08-24: Simon Goldschmidt
|
||||
* pbuf.c: fixed bug #34112 Odd check in pbuf_alloced_custom (typo)
|
||||
|
||||
2011-08-24: Simon Goldschmidt
|
||||
* dhcp.c: fixed bug #34122 dhcp: hostname can overflow
|
||||
|
||||
2011-08-24: Simon Goldschmidt
|
||||
* netif.c: fixed bug #34121 netif_add/netif_set_ipaddr fail on NULL ipaddr
|
||||
|
||||
2011-08-22: Simon Goldschmidt
|
||||
* tcp_out.c: fixed bug #33962 TF_FIN not always set after FIN is sent. (This
|
||||
merely prevents nagle from not transmitting fast after closing.)
|
||||
|
||||
2011-07-22: Simon Goldschmidt
|
||||
* api_lib.c, api_msg.c, sockets.c, api.h: fixed bug #31084 (socket API returns
|
||||
always EMSGSIZE on non-blocking sockets if data size > send buffers) -> now
|
||||
lwip_send() sends as much as possible for non-blocking sockets
|
||||
|
||||
2011-07-22: Simon Goldschmidt
|
||||
* pbuf.c/.h, timers.c: freeing ooseq pbufs when the pbuf pool is empty implemented
|
||||
for NO_SYS==1: when not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ()
|
||||
at regular intervals from main level.
|
||||
|
||||
2011-07-21: Simon Goldschmidt
|
||||
* etharp.c: fixed bug #33551 (ARP entries may time out although in use) by
|
||||
sending an ARP request when an ARP entry is used in the last minute before
|
||||
it would time out.
|
||||
|
||||
2011-07-04: Simon Goldschmidt
|
||||
* sys_arch.txt: Fixed documentation after changing sys arch prototypes for 1.4.0.
|
||||
|
||||
2011-06-26: Simon Goldschmidt
|
||||
* tcp.c: fixed bug #31723 (tcp_kill_prio() kills pcbs with the same prio) by
|
||||
updating its documentation only.
|
||||
|
||||
2011-06-26: Simon Goldschmidt
|
||||
* mem.c: fixed bug #33545: With MEM_USE_POOLS==1, mem_malloc can return an
|
||||
unaligned pointer.
|
||||
|
||||
2011-06-26: Simon Goldschmidt
|
||||
* mem.c: fixed bug #33544 "warning in mem.c in lwip 1.4.0 with NO_SYS=1"
|
||||
|
||||
2011-05-25: Simon Goldschmidt
|
||||
* tcp.c: fixed bug #33398 (pointless conversion when checking TCP port range)
|
||||
|
||||
|
||||
|
||||
(STABLE-1.4.0)
|
||||
|
||||
++ New features:
|
||||
|
||||
2011-03-27: Simon Goldschmidt
|
||||
* tcp_impl.h, tcp_in.c, tcp_out.c: Removed 'dataptr' from 'struct tcp_seg' and
|
||||
calculate it in tcp_zero_window_probe (the only place where it was used).
|
||||
|
||||
2010-11-21: Simon Goldschmidt
|
||||
* dhcp.c/.h: Added a function to deallocate the struct dhcp from a netif
|
||||
(fixes bug #31525).
|
||||
|
||||
2010-07-12: Simon Goldschmidt (patch by Stephane Lesage)
|
||||
* ip.c, udp.c/.h, pbuf.h, sockets.c: task #10495: Added support for
|
||||
IP_MULTICAST_LOOP at socket- and raw-API level.
|
||||
|
||||
2010-06-16: Simon Goldschmidt
|
||||
* ip.c: Added an optional define (LWIP_IP_ACCEPT_UDP_PORT) that can allow
|
||||
link-layer-addressed UDP traffic to be received while a netif is down (just
|
||||
like DHCP during configuration)
|
||||
|
||||
2010-05-22: Simon Goldschmidt
|
||||
* many many files: bug #27352: removed packing from ip_addr_t, the packed
|
||||
version is now only used in protocol headers. Added global storage for
|
||||
current src/dest IP address while in input functions.
|
||||
|
||||
2010-05-16: Simon Goldschmidt
|
||||
* def.h: task #10391: Add preprocessor-macros for compile-time htonl
|
||||
calculation (and use them throughout the stack where applicable)
|
||||
|
||||
2010-05-16: Simon Goldschmidt
|
||||
* opt.h, memp_std.h, memp.c, ppp_oe.h/.c: PPPoE now uses its own MEMP pool
|
||||
instead of the heap (moved struct pppoe_softc from ppp_oe.c to ppp_oe.h)
|
||||
|
||||
2010-05-16: Simon Goldschmidt
|
||||
* opt.h, memp_std.h, dns.h/.c: DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses its own
|
||||
MEMP pool instead of the heap
|
||||
|
||||
2010-05-13: Simon Goldschmidt
|
||||
* tcp.c, udp.c: task #6995: Implement SO_REUSEADDR (correctly), added
|
||||
new option SO_REUSE_RXTOALL to pass received UDP broadcast/multicast
|
||||
packets to more than one pcb.
|
||||
|
||||
2010-05-02: Simon Goldschmidt
|
||||
* netbuf.h/.c, sockets.c, api_msg.c: use checksum-on-copy for sending
|
||||
UDP data for LWIP_NETIF_TX_SINGLE_PBUF==1
|
||||
|
||||
2010-04-30: Simon Goldschmidt
|
||||
* udp.h/.c, pbuf.h/.c: task #6849: added udp_send(_to/_if) functions that
|
||||
take a precalculated checksum, added pbuf_fill_chksum() to copy data
|
||||
into a pbuf and at the same time calculating the checksum for that data
|
||||
|
||||
2010-04-29: Simon Goldschmidt
|
||||
* ip_addr.h, etharp.h/.c, autoip.c: Create overridable macros for copying
|
||||
2-byte-aligned IP addresses and MAC addresses
|
||||
|
||||
2010-04-28: Patch by Bill Auerbach
|
||||
* ip.c: Inline generating IP checksum to save a function call
|
||||
|
||||
2010-04-14: Simon Goldschmidt
|
||||
* tcpip.h/.c, timers.c: Added an overridable define to get informed when the
|
||||
tcpip_thread processes messages or timeouts to implement a watchdog.
|
||||
|
||||
2010-03-28: Simon Goldschmidt
|
||||
* ip_frag.c: create a new (contiguous) PBUF_RAM for every outgoing
|
||||
fragment if LWIP_NETIF_TX_SINGLE_PBUF==1
|
||||
|
||||
2010-03-27: Simon Goldschmidt
|
||||
* etharp.c: Speedup TX by moving code from find_entry to etharp_output/
|
||||
etharp_query to prevent unnecessary function calls (inspired by
|
||||
patch #7135).
|
||||
|
||||
2010-03-20: Simon Goldschmidt
|
||||
* opt.h, tcpip.c/.h: Added an option to disable tcpip_(un)timeout code
|
||||
since the linker cannot do this automatically to save space.
|
||||
|
||||
2010-03-20: Simon Goldschmidt
|
||||
* opt.h, etharp.c/.h: Added support for static ARP table entries
|
||||
|
||||
2010-03-14: Simon Goldschmidt
|
||||
* tcp_impl.h, tcp_out.c, inet_chksum.h/.c: task #6849: Calculate checksum
|
||||
when creating TCP segments, not when (re-)transmitting them.
|
||||
|
||||
2010-03-07: Simon Goldschmidt
|
||||
* sockets.c: bug #28775 (select/event_callback: only check select_cb_list
|
||||
on change) plus use SYS_LIGHTWEIGHT_PROT to protect the select code.
|
||||
This should speed up receiving data on sockets as the select code in
|
||||
event_callback is only executed when select is waiting.
|
||||
|
||||
2010-03-06: Simon Goldschmidt
|
||||
* tcp_out.c: task #7013 (Create option to have all packets delivered to
|
||||
netif->output in one piece): Always copy to try to create single pbufs
|
||||
in tcp_write.
|
||||
|
||||
2010-03-06: Simon Goldschmidt
|
||||
* api.h, api_lib.c, sockets.c: task #10167 (sockets: speed up TCP recv
|
||||
by not allocating a netbuf): added function netconn_recv_tcp_pbuf()
|
||||
for tcp netconns to receive pbufs, not netbufs; use that function
|
||||
for tcp sockets.
|
||||
|
||||
2010-03-05: Jakob Ole Stoklundsen / Simon Goldschmidt
|
||||
* opt.h, tcp.h, tcp_impl.h, tcp.c, tcp_in.c, tcp_out.c: task #7040:
|
||||
Work on tcp_enqueue: Don't waste memory when chaining segments,
|
||||
added option TCP_OVERSIZE to prevent creating many small pbufs when
|
||||
calling tcp_write with many small blocks of data. Instead, pbufs are
|
||||
allocated larger than needed and the space is used for later calls to
|
||||
tcp_write.
|
||||
|
||||
2010-02-21: Simon Goldschmidt
|
||||
* stats.c/.h: Added const char* name to mem- and memp-stats for easier
|
||||
debugging.
|
||||
|
||||
2010-02-21: Simon Goldschmidt
|
||||
* tcp.h (and usages), added tcp_impl.h: Splitted API and internal
|
||||
implementation of tcp to make API usage cleare to application programmers
|
||||
|
||||
2010-02-14: Simon Goldschmidt/Stephane Lesage
|
||||
* ip_addr.h: Improved some defines working on ip addresses, added faster
|
||||
macro to copy addresses that cannot be NULL
|
||||
|
||||
2010-02-13: Simon Goldschmidt
|
||||
* api.h, api_lib.c, api_msg.c, sockets.c: task #7865 (implement non-
|
||||
blocking send operation)
|
||||
|
||||
2010-02-12: Simon Goldschmidt
|
||||
* sockets.c/.h: Added a minimal version of posix fctl() to have a
|
||||
standardised way to set O_NONBLOCK for nonblocking sockets.
|
||||
|
||||
2010-02-12: Simon Goldschmidt
|
||||
* dhcp.c/.h, autoip.c/.h: task #10139 (Prefer statically allocated
|
||||
memory): added autoip_set_struct() and dhcp_set_struct() to let autoip
|
||||
and dhcp work with user-allocated structs instead of callin mem_malloc
|
||||
|
||||
2010-02-12: Simon Goldschmidt/Jeff Barber
|
||||
* tcp.c/h: patch #6865 (SO_REUSEADDR for TCP): if pcb.so_options has
|
||||
SOF_REUSEADDR set, allow binding to endpoint in TIME_WAIT
|
||||
|
||||
2010-02-12: Simon Goldschmidt
|
||||
* sys layer: task #10139 (Prefer statically allocated memory): converted
|
||||
mbox and semaphore functions to take pointers to sys_mbox_t/sys_sem_t;
|
||||
converted sys_mbox_new/sys_sem_new to take pointers and return err_t;
|
||||
task #7212: Add Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX
|
||||
to let sys.h use binary semaphores instead of mutexes - as before)
|
||||
|
||||
2010-02-09: Simon Goldschmidt (Simon Kallweit)
|
||||
* timers.c/.h: Added function sys_restart_timeouts() from patch #7085
|
||||
(Restart system timeout handling)
|
||||
|
||||
2010-02-09: Simon Goldschmidt
|
||||
* netif.c/.h, removed loopif.c/.h: task #10153 (Integrate loopif into
|
||||
netif.c) - loopif does not have to be created by the port any more,
|
||||
just define LWIP_HAVE_LOOPIF to 1.
|
||||
|
||||
2010-02-08: Simon Goldschmidt
|
||||
* inet.h, ip_addr.c/.h: Added reentrant versions of inet_ntoa/ipaddr_ntoa
|
||||
inet_ntoa_r/ipaddr_ntoa_r
|
||||
|
||||
2010-02-08: Simon Goldschmidt
|
||||
* netif.h: Added netif_s/get_igmp_mac_filter() macros
|
||||
|
||||
2010-02-05: Simon Goldschmidt
|
||||
* netif.h: Added function-like macros to get/set the hostname on a netif
|
||||
|
||||
2010-02-04: Simon Goldschmidt
|
||||
* nearly every file: Replaced struct ip_addr by typedef ip_addr_t to
|
||||
make changing the actual implementation behind the typedef easier.
|
||||
|
||||
2010-02-01: Simon Goldschmidt
|
||||
* opt.h, memp_std.h, dns.h, netdb.c, memp.c: Let netdb use a memp pool
|
||||
for allocating memory when getaddrinfo() is called.
|
||||
|
||||
2010-01-31: Simon Goldschmidt
|
||||
* dhcp.h, dhcp.c: Reworked the code that parses DHCP options: parse
|
||||
them once instead of parsing for every option. This also removes
|
||||
the need for mem_malloc from dhcp_recv and makes it possible to
|
||||
correctly retrieve the BOOTP file.
|
||||
|
||||
2010-01-30: simon Goldschmidt
|
||||
* sockets.c: Use SYS_LIGHTWEIGHT_PROT instead of a semaphore to protect
|
||||
the sockets array.
|
||||
|
||||
2010-01-29: Simon Goldschmidt (patch by Laura Garrett)
|
||||
* api.h, api_msg.c, sockets.c: Added except set support in select
|
||||
(patch #6860)
|
||||
|
||||
2010-01-29: Simon Goldschmidt (patch by Laura Garrett)
|
||||
* api.h, sockets.h, err.h, api_lib.c, api_msg.c, sockets.c, err.c:
|
||||
Add non-blocking support for connect (partly from patch #6860),
|
||||
plus many cleanups in socket & netconn API.
|
||||
|
||||
2010-01-27: Simon Goldschmidt
|
||||
* opt.h, tcp.h, init.c, api_msg.c: Added TCP_SNDQUEUELOWAT corresponding
|
||||
to TCP_SNDLOWAT and added tcp_sndqueuelen() - this fixes bug #28605
|
||||
|
||||
2010-01-26: Simon Goldschmidt
|
||||
* snmp: Use memp pools for snmp instead of the heap; added 4 new pools.
|
||||
|
||||
2010-01-14: Simon Goldschmidt
|
||||
* ppp.c/.h: Fixed bug #27856: PPP: Set netif link- and status-callback
|
||||
by adding ppp_set_netif_statuscallback()/ppp_set_netif_linkcallback()
|
||||
|
||||
2010-01-13: Simon Goldschmidt
|
||||
* mem.c: The heap now may be moved to user-defined memory by defining
|
||||
LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address
|
||||
(patch #6966 and bug #26133)
|
||||
|
||||
2010-01-10: Simon Goldschmidt (Bill Auerbach)
|
||||
* opt.h, memp.c: patch #6822 (Add option to place memory pools in
|
||||
separate arrays)
|
||||
|
||||
2010-01-10: Simon Goldschmidt
|
||||
* init.c, igmp.c: patch #6463 (IGMP - Adding Random Delay): added define
|
||||
LWIP_RAND() for lwip-wide randomization (to be defined in cc.h)
|
||||
|
||||
2009-12-31: Simon Goldschmidt
|
||||
* tcpip.c, init.c, memp.c, sys.c, memp_std.h, sys.h, tcpip.h
|
||||
added timers.c/.h: Separated timer implementation from semaphore/mbox
|
||||
implementation, moved timer implementation to timers.c/.h, timers are
|
||||
now only called from tcpip_thread or by explicitly checking them.
|
||||
(TASK#7235)
|
||||
|
||||
2009-12-27: Simon Goldschmidt
|
||||
* opt.h, etharp.h/.c, init.c, tcpip.c: Added an additional option
|
||||
LWIP_ETHERNET to support ethernet without ARP (necessary for pure PPPoE)
|
||||
|
||||
|
||||
++ Bugfixes:
|
||||
|
||||
2011-04-20: Simon Goldschmidt
|
||||
* sys_arch.txt: sys_arch_timeouts() is not needed any more.
|
||||
|
||||
2011-04-13: Simon Goldschmidt
|
||||
* tcp.c, udp.c: Fixed bug #33048 (Bad range for IP source port numbers) by
|
||||
using ports in the IANA private/dynamic range (49152 through 65535).
|
||||
|
||||
2011-03-29: Simon Goldschmidt, patch by Emil Lhungdahl:
|
||||
* etharp.h/.c: Fixed broken VLAN support.
|
||||
|
||||
2011-03-27: Simon Goldschmidt
|
||||
* tcp.c: Fixed bug #32926 (TCP_RMV(&tcp_bound_pcbs) is called on unbound tcp
|
||||
pcbs) by checking if the pcb was bound (local_port != 0).
|
||||
|
||||
2011-03-27: Simon Goldschmidt
|
||||
* ppp.c: Fixed bug #32280 (ppp: a pbuf is freed twice)
|
||||
|
||||
2011-03-27: Simon Goldschmidt
|
||||
* sockets.c: Fixed bug #32906: lwip_connect+lwip_send did not work for udp and
|
||||
raw pcbs with LWIP_TCPIP_CORE_LOCKING==1.
|
||||
|
||||
2011-03-27: Simon Goldschmidt
|
||||
* tcp_out.c: Fixed bug #32820 (Outgoing TCP connections created before route
|
||||
is present never times out) by starting retransmission timer before checking
|
||||
route.
|
||||
|
||||
2011-03-22: Simon Goldschmidt
|
||||
* ppp.c: Fixed bug #32648 (PPP code crashes when terminating a link) by only
|
||||
calling sio_read_abort() if the file descriptor is valid.
|
||||
|
||||
2011-03-14: Simon Goldschmidt
|
||||
* err.h/.c, sockets.c, api_msg.c: fixed bug #31748 (Calling non-blocking connect
|
||||
more than once can render a socket useless) since it mainly involves changing
|
||||
"FATAL" classification of error codes: ERR_USE and ERR_ISCONN just aren't fatal.
|
||||
|
||||
2011-03-13: Simon Goldschmidt
|
||||
* sockets.c: fixed bug #32769 (ESHUTDOWN is linux-specific) by fixing
|
||||
err_to_errno_table (ERR_CLSD: ENOTCONN instead of ESHUTDOWN), ERR_ISCONN:
|
||||
use EALRADY instead of -1
|
||||
|
||||
2011-03-13: Simon Goldschmidt
|
||||
* api_lib.c: netconn_accept: return ERR_ABRT instead of ERR_CLSD if the
|
||||
connection has been aborted by err_tcp (since this is not a normal closing
|
||||
procedure).
|
||||
|
||||
2011-03-13: Simon Goldschmidt
|
||||
* tcp.c: tcp_bind: return ERR_VAL instead of ERR_ISCONN when trying to bind
|
||||
with pcb->state != CLOSED
|
||||
|
||||
2011-02-17: Simon Goldschmidt
|
||||
* rawapi.txt: Fixed bug #32561 tcp_poll argument definition out-of-order in
|
||||
documentation
|
||||
|
||||
2011-02-17: Simon Goldschmidt
|
||||
* many files: Added missing U/UL modifiers to fix 16-bit-arch portability.
|
||||
|
||||
2011-01-24: Simon Goldschmidt
|
||||
* sockets.c: Fixed bug #31741: lwip_select seems to have threading problems
|
||||
|
||||
2010-12-02: Simon Goldschmidt
|
||||
* err.h: Fixed ERR_IS_FATAL so that ERR_WOULDBLOCK is not fatal.
|
||||
|
||||
2010-11-23: Simon Goldschmidt
|
||||
* api.h, api_lib.c, api_msg.c, sockets.c: netconn.recv_avail is only used for
|
||||
LWIP_SO_RCVBUF and ioctl/FIONREAD.
|
||||
|
||||
2010-11-23: Simon Goldschmidt
|
||||
* etharp.c: Fixed bug #31720: ARP-queueing: RFC 1122 recommends to queue at
|
||||
least 1 packet -> ARP_QUEUEING==0 now queues the most recent packet.
|
||||
|
||||
2010-11-23: Simon Goldschmidt
|
||||
* tcp_in.c: Fixed bug #30577: tcp_input: don't discard ACK-only packets after
|
||||
refusing 'refused_data' again.
|
||||
|
||||
2010-11-22: Simon Goldschmidt
|
||||
* sockets.c: Fixed bug #31590: getsockopt(... SO_ERROR ...) gives EINPROGRESS
|
||||
after a successful nonblocking connection.
|
||||
|
||||
2010-11-22: Simon Goldschmidt
|
||||
* etharp.c: Fixed bug #31722: IP packets sent with an AutoIP source addr
|
||||
must be sent link-local
|
||||
|
||||
2010-11-22: Simon Goldschmidt
|
||||
* timers.c: patch #7329: tcp_timer_needed prototype was ifdef'ed out for
|
||||
LWIP_TIMERS==0
|
||||
|
||||
2010-11-20: Simon Goldschmidt
|
||||
* sockets.c: Fixed bug #31170: lwip_setsockopt() does not set socket number
|
||||
|
||||
2010-11-20: Simon Goldschmidt
|
||||
* sockets.h: Fixed bug #31304: Changed SHUT_RD, SHUT_WR and SHUT_RDWR to
|
||||
resemble other stacks.
|
||||
|
||||
2010-11-20: Simon Goldschmidt
|
||||
* dns.c: Fixed bug #31535: TCP_SND_QUEUELEN must be at least 2 or else
|
||||
no-copy TCP writes will never succeed.
|
||||
|
||||
2010-11-20: Simon Goldschmidt
|
||||
* dns.c: Fixed bug #31701: Error return value from dns_gethostbyname() does
|
||||
not match documentation: return ERR_ARG instead of ERR_VAL if not
|
||||
initialized or wrong argument.
|
||||
|
||||
2010-10-20: Simon Goldschmidt
|
||||
* sockets.h: Fixed bug #31385: sizeof(struct sockaddr) is 30 but should be 16
|
||||
|
||||
2010-10-05: Simon Goldschmidt
|
||||
* dhcp.c: Once again fixed #30038: DHCP/AutoIP cooperation failed when
|
||||
replugging the network cable after an AutoIP address was assigned.
|
||||
|
||||
2010-08-10: Simon Goldschmidt
|
||||
* tcp.c: Fixed bug #30728: tcp_new_port() did not check listen pcbs
|
||||
|
||||
2010-08-03: Simon Goldschmidt
|
||||
* udp.c, raw.c: Don't chain empty pbufs when sending them (fixes bug #30625)
|
||||
|
||||
2010-08-01: Simon Goldschmidt (patch by Greg Renda)
|
||||
* ppp.c: Applied patch #7264 (PPP protocols are rejected incorrectly on big
|
||||
endian architectures)
|
||||
|
||||
2010-07-28: Simon Goldschmidt
|
||||
* api_lib.c, api_msg.c, sockets.c, mib2.c: Fixed compilation with TCP or UDP
|
||||
disabled.
|
||||
|
||||
2010-07-27: Simon Goldschmidt
|
||||
* tcp.c: Fixed bug #30565 (tcp_connect() check bound list): that check did no
|
||||
harm but never did anything
|
||||
|
||||
2010-07-21: Simon Goldschmidt
|
||||
* ip.c: Fixed invalid fix for bug #30402 (CHECKSUM_GEN_IP_INLINE does not
|
||||
add IP options)
|
||||
|
||||
2010-07-16: Kieran Mansley
|
||||
* msg_in.c: Fixed SNMP ASN constant defines to not use ! operator
|
||||
|
||||
2010-07-10: Simon Goldschmidt
|
||||
* ip.c: Fixed bug #30402: CHECKSUM_GEN_IP_INLINE does not add IP options
|
||||
|
||||
2010-06-30: Simon Goldschmidt
|
||||
* api_msg.c: fixed bug #30300 (shutdown parameter was not initialized in
|
||||
netconn_delete)
|
||||
|
||||
2010-06-28: Kieran Mansley
|
||||
* timers.c remove unportable printing of C function pointers
|
||||
|
||||
2010-06-24: Simon Goldschmidt
|
||||
* init.c, timers.c/.h, opt.h, memp_std.h: From patch #7221: added flag
|
||||
NO_SYS_NO_TIMERS to drop timer support for NO_SYS==1 for easier upgrading
|
||||
|
||||
2010-06-24: Simon Goldschmidt
|
||||
* api(_lib).c/.h, api_msg.c/.h, sockets.c/.h: Fixed bug #10088: Correctly
|
||||
implemented shutdown at socket level.
|
||||
|
||||
2010-06-21: Simon Goldschmidt
|
||||
* pbuf.c/.h, ip_frag.c/.h, opt.h, memp_std.h: Fixed bug #29361 (ip_frag has
|
||||
problems with zero-copy DMA MACs) by adding custom pbufs and implementing
|
||||
custom pbufs that reference other (original) pbufs. Additionally set
|
||||
IP_FRAG_USES_STATIC_BUF=0 as default to be on the safe side.
|
||||
|
||||
2010-06-15: Simon Goldschmidt
|
||||
* dhcp.c: Fixed bug #29970: DHCP endian issue parsing option responses
|
||||
|
||||
2010-06-14: Simon Goldschmidt
|
||||
* autoip.c: Fixed bug #30039: AutoIP does not reuse previous addresses
|
||||
|
||||
2010-06-12: Simon Goldschmidt
|
||||
* dhcp.c: Fixed bug #30038: dhcp_network_changed doesn't reset AUTOIP coop
|
||||
state
|
||||
|
||||
2010-05-17: Simon Goldschmidt
|
||||
* netdb.c: Correctly NULL-terminate h_addr_list
|
||||
|
||||
2010-05-16: Simon Goldschmidt
|
||||
* def.h/.c: changed the semantics of LWIP_PREFIX_BYTEORDER_FUNCS to prevent
|
||||
"symbol already defined" i.e. when linking to winsock
|
||||
|
||||
2010-05-05: Simon Goldschmidt
|
||||
* def.h, timers.c: Fixed bug #29769 (sys_check_timeouts: sys_now() may
|
||||
overflow)
|
||||
|
||||
2010-04-21: Simon Goldschmidt
|
||||
* api_msg.c: Fixed bug #29617 (sometime cause stall on delete listening
|
||||
connection)
|
||||
|
||||
2010-03-28: Luca Ceresoli
|
||||
* ip_addr.c/.h: patch #7143: Add a few missing const qualifiers
|
||||
|
||||
2010-03-27: Luca Ceresoli
|
||||
* mib2.c: patch #7130: remove meaningless const qualifiers
|
||||
|
||||
2010-03-26: Simon Goldschmidt
|
||||
* tcp_out.c: Make LWIP_NETIF_TX_SINGLE_PBUF work for TCP, too
|
||||
|
||||
2010-03-26: Simon Goldschmidt
|
||||
* various files: Fixed compiling with different options disabled (TCP/UDP),
|
||||
triggered by bug #29345; don't allocate acceptmbox if LWIP_TCP is disabled
|
||||
|
||||
2010-03-25: Simon Goldschmidt
|
||||
* sockets.c: Fixed bug #29332: lwip_select() processes readset incorrectly
|
||||
|
||||
2010-03-25: Simon Goldschmidt
|
||||
* tcp_in.c, test_tcp_oos.c: Fixed bug #29080: Correctly handle remote side
|
||||
overrunning our rcv_wnd in ooseq case.
|
||||
|
||||
2010-03-22: Simon Goldschmidt
|
||||
* tcp.c: tcp_listen() did not copy the pcb's prio.
|
||||
|
||||
2010-03-19: Simon Goldschmidt
|
||||
* snmp_msg.c: Fixed bug #29256: SNMP Trap address was not correctly set
|
||||
|
||||
2010-03-14: Simon Goldschmidt
|
||||
* opt.h, etharp.h: Fixed bug #29148 (Incorrect PBUF_POOL_BUFSIZE for ports
|
||||
where ETH_PAD_SIZE > 0) by moving definition of ETH_PAD_SIZE to opt.h
|
||||
and basing PBUF_LINK_HLEN on it.
|
||||
|
||||
2010-03-08: Simon Goldschmidt
|
||||
* netif.c, ipv4/ip.c: task #10241 (AutoIP: don't break existing connections
|
||||
when assiging routable address): when checking incoming packets and
|
||||
aborting existing connection on address change, filter out link-local
|
||||
addresses.
|
||||
|
||||
2010-03-06: Simon Goldschmidt
|
||||
* sockets.c: Fixed LWIP_NETIF_TX_SINGLE_PBUF for LWIP_TCPIP_CORE_LOCKING
|
||||
|
||||
2010-03-06: Simon Goldschmidt
|
||||
* ipv4/ip.c: Don't try to forward link-local addresses
|
||||
|
||||
2010-03-06: Simon Goldschmidt
|
||||
* etharp.c: Fixed bug #29087: etharp: don't send packets for LinkLocal-
|
||||
addresses to gw
|
||||
|
||||
2010-03-05: Simon Goldschmidt
|
||||
* dhcp.c: Fixed bug #29072: Correctly set ciaddr based on message-type
|
||||
and state.
|
||||
|
||||
2010-03-05: Simon Goldschmidt
|
||||
* api_msg.c: Correctly set TCP_WRITE_FLAG_MORE when netconn_write is split
|
||||
into multiple calls to tcp_write.
|
||||
|
||||
2010-02-21: Simon Goldschmidt
|
||||
* opt.h, mem.h, dns.c: task #10140: Remove DNS_USES_STATIC_BUF (keep
|
||||
the implementation of DNS_USES_STATIC_BUF==1)
|
||||
|
||||
2010-02-20: Simon Goldschmidt
|
||||
* tcp.h, tcp.c, tcp_in.c, tcp_out.c: Task #10088: Correctly implement
|
||||
close() vs. shutdown(). Now the application does not get any more
|
||||
recv callbacks after calling tcp_close(). Added tcp_shutdown().
|
||||
|
||||
2010-02-19: Simon Goldschmidt
|
||||
* mem.c/.h, pbuf.c: Renamed mem_realloc() to mem_trim() to prevent
|
||||
confusion with realloc()
|
||||
|
||||
2010-02-15: Simon Goldschmidt/Stephane Lesage
|
||||
* netif.c/.h: Link status does not depend on LWIP_NETIF_LINK_CALLBACK
|
||||
(fixes bug #28899)
|
||||
|
||||
2010-02-14: Simon Goldschmidt
|
||||
* netif.c: Fixed bug #28877 (Duplicate ARP gratuitous packet with
|
||||
LWIP_NETIF_LINK_CALLBACK set on) by only sending if both link- and
|
||||
admin-status of a netif are up
|
||||
|
||||
2010-02-14: Simon Goldschmidt
|
||||
* opt.h: Disable ETHARP_TRUST_IP_MAC by default since it slows down packet
|
||||
reception and is not really necessary
|
||||
|
||||
2010-02-14: Simon Goldschmidt
|
||||
* etharp.c/.h: Fixed ARP input processing: only add a new entry if a
|
||||
request was directed as us (RFC 826, Packet Reception), otherwise
|
||||
only update existing entries; internalized some functions
|
||||
|
||||
2010-02-14: Simon Goldschmidt
|
||||
* netif.h, etharp.c, tcpip.c: Fixed bug #28183 (ARP and TCP/IP cannot be
|
||||
disabled on netif used for PPPoE) by adding a new netif flag
|
||||
(NETIF_FLAG_ETHERNET) that tells the stack the device is an ethernet
|
||||
device but prevents usage of ARP (so that ethernet_input can be used
|
||||
for PPPoE).
|
||||
|
||||
2010-02-12: Simon Goldschmidt
|
||||
* netif.c: netif_set_link_up/down: only do something if the link state
|
||||
actually changes
|
||||
|
||||
2010-02-12: Simon Goldschmidt/Stephane Lesage
|
||||
* api_msg.c: Fixed bug #28865 (Cannot close socket/netconn in non-blocking
|
||||
connect)
|
||||
|
||||
2010-02-12: Simon Goldschmidt
|
||||
* mem.h: Fixed bug #28866 (mem_realloc function defined in mem.h)
|
||||
|
||||
2010-02-09: Simon Goldschmidt
|
||||
* api_lib.c, api_msg.c, sockets.c, api.h, api_msg.h: Fixed bug #22110
|
||||
(recv() makes receive window update for data that wasn't received by
|
||||
application)
|
||||
|
||||
2010-02-09: Simon Goldschmidt/Stephane Lesage
|
||||
* sockets.c: Fixed bug #28853 (lwip_recvfrom() returns 0 on receive time-out
|
||||
or any netconn_recv() error)
|
||||
|
||||
2010-02-09: Simon Goldschmidt
|
||||
* ppp.c: task #10154 (PPP: Update snmp in/out counters for tx/rx packets)
|
||||
|
||||
2010-02-09: Simon Goldschmidt
|
||||
* netif.c: For loopback packets, adjust the stats- and snmp-counters
|
||||
for the loopback netif.
|
||||
|
||||
2010-02-08: Simon Goldschmidt
|
||||
* igmp.c/.h, ip.h: Moved most defines from igmp.h to igmp.c for clarity
|
||||
since they are not used anywhere else.
|
||||
|
||||
2010-02-08: Simon Goldschmidt (St<53>phane Lesage)
|
||||
* igmp.c, igmp.h, stats.c, stats.h: Improved IGMP stats
|
||||
(patch from bug #28798)
|
||||
|
||||
2010-02-08: Simon Goldschmidt (St<53>phane Lesage)
|
||||
* igmp.c: Fixed bug #28798 (Error in "Max Response Time" processing) and
|
||||
another bug when LWIP_RAND() returns zero.
|
||||
|
||||
2010-02-04: Simon Goldschmidt
|
||||
* nearly every file: Use macros defined in ip_addr.h (some of them new)
|
||||
to work with IP addresses (preparation for bug #27352 - Change ip_addr
|
||||
from struct to typedef (u32_t) - and better code).
|
||||
|
||||
2010-01-31: Simon Goldschmidt
|
||||
* netif.c: Don't call the link-callback from netif_set_up/down() since
|
||||
this invalidly retriggers DHCP.
|
||||
|
||||
2010-01-29: Simon Goldschmidt
|
||||
* ip_addr.h, inet.h, def.h, inet.c, def.c, more: Cleanly separate the
|
||||
portability file inet.h and its contents from the stack: moved htonX-
|
||||
functions to def.h (and the new def.c - they are not ipv4 dependent),
|
||||
let inet.h depend on ip_addr.h and not the other way round.
|
||||
This fixes bug #28732.
|
||||
|
||||
2010-01-28: Kieran Mansley
|
||||
* tcp.c: Ensure ssthresh >= 2*MSS
|
||||
|
||||
2010-01-27: Simon Goldschmidt
|
||||
* tcp.h, tcp.c, tcp_in.c: Fixed bug #27871: Calling tcp_abort() in recv
|
||||
callback can lead to accessing unallocated memory. As a consequence,
|
||||
ERR_ABRT means the application has called tcp_abort()!
|
||||
|
||||
2010-01-25: Simon Goldschmidt
|
||||
* snmp_structs.h, msg_in.c: Partly fixed bug #22070 (MIB_OBJECT_WRITE_ONLY
|
||||
not implemented in SNMP): write-only or not-accessible are still
|
||||
returned by getnext (though not by get)
|
||||
|
||||
2010-01-24: Simon Goldschmidt
|
||||
* snmp: Renamed the private mib node from 'private' to 'mib_private' to
|
||||
not use reserved C/C++ keywords
|
||||
|
||||
2010-01-23: Simon Goldschmidt
|
||||
* sockets.c: Fixed bug #28716: select() returns 0 after waiting for less
|
||||
than 1 ms
|
||||
|
||||
2010-01-21: Simon Goldschmidt
|
||||
* tcp.c, api_msg.c: Fixed bug #28651 (tcp_connect: no callbacks called
|
||||
if tcp_enqueue fails) both in raw- and netconn-API
|
||||
|
||||
2010-01-19: Simon Goldschmidt
|
||||
* api_msg.c: Fixed bug #27316: netconn: Possible deadlock in err_tcp
|
||||
|
||||
2010-01-18: Iordan Neshev/Simon Goldschmidt
|
||||
* src/netif/ppp: reorganised PPP sourcecode to 2.3.11 including some
|
||||
bugfix backports from 2.4.x.
|
||||
|
||||
2010-01-18: Simon Goldschmidt
|
||||
* mem.c: Fixed bug #28679: mem_realloc calculates mem_stats wrong
|
||||
|
||||
2010-01-17: Simon Goldschmidt
|
||||
* api_lib.c, api_msg.c, (api_msg.h, api.h, sockets.c, tcpip.c):
|
||||
task #10102: "netconn: clean up conn->err threading issues" by adding
|
||||
error return value to struct api_msg_msg
|
||||
|
||||
2010-01-17: Simon Goldschmidt
|
||||
* api.h, api_lib.c, sockets.c: Changed netconn_recv() and netconn_accept()
|
||||
to return err_t (bugs #27709 and #28087)
|
||||
|
||||
2010-01-14: Simon Goldschmidt
|
||||
* ...: Use typedef for function prototypes throughout the stack.
|
||||
|
||||
2010-01-13: Simon Goldschmidt
|
||||
* api_msg.h/.c, api_lib.c: Fixed bug #26672 (close connection when receive
|
||||
window = 0) by correctly draining recvmbox/acceptmbox
|
||||
|
||||
2010-01-11: Simon Goldschmidt
|
||||
* pap.c: Fixed bug #13315 (PPP PAP authentication can result in
|
||||
erroneous callbacks) by copying the code from recent pppd
|
||||
|
||||
2010-01-10: Simon Goldschmidt
|
||||
* raw.c: Fixed bug #28506 (raw_bind should filter received packets)
|
||||
|
||||
2010-01-10: Simon Goldschmidt
|
||||
* tcp.h/.c: bug #28127 (remove call to tcp_output() from tcp_ack(_now)())
|
||||
|
||||
2010-01-08: Simon Goldschmidt
|
||||
* sockets.c: Fixed bug #28519 (lwip_recvfrom bug with len > 65535)
|
||||
|
||||
2010-01-08: Simon Goldschmidt
|
||||
* dns.c: Copy hostname for DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1 since string
|
||||
passed to dns_local_addhost() might be volatile
|
||||
|
||||
2010-01-07: Simon Goldschmidt
|
||||
* timers.c, tcp.h: Call tcp_timer_needed() with NO_SYS==1, too
|
||||
|
||||
2010-01-06: Simon Goldschmidt
|
||||
* netdb.h: Fixed bug #28496: missing include guards in netdb.h
|
||||
|
||||
2009-12-31: Simon Goldschmidt
|
||||
* many ppp files: Reorganised PPP source code from ucip structure to pppd
|
||||
structure to easily compare our code against the pppd code (around v2.3.1)
|
||||
|
||||
2009-12-27: Simon Goldschmidt
|
||||
* tcp_in.c: Another fix for bug #28241 (ooseq processing) and adapted
|
||||
unit test
|
||||
|
||||
|
||||
(STABLE-1.3.2)
|
||||
|
||||
|
||||
144
UPGRADING
Normal file
144
UPGRADING
Normal file
@@ -0,0 +1,144 @@
|
||||
This file lists major changes between release versions that require
|
||||
ports or applications to be changed. Use it to update a port or an
|
||||
application written for an older version of lwIP to correctly work
|
||||
with newer versions.
|
||||
|
||||
|
||||
(CVS HEAD)
|
||||
|
||||
* [Enter new changes just after this line - do not remove this line]
|
||||
|
||||
++ Application changes:
|
||||
|
||||
* Replaced struct ip_addr by typedef ip_addr_t (struct ip_addr is kept for
|
||||
compatibility to old applications, but will be removed in the future).
|
||||
|
||||
* Renamed mem_realloc() to mem_trim() to prevent confusion with realloc()
|
||||
|
||||
+++ Raw API:
|
||||
* Changed the semantics of tcp_close() (since it was rather a
|
||||
shutdown before): Now the application does *NOT* get any calls to the recv
|
||||
callback (aside from NULL/closed) after calling tcp_close()
|
||||
|
||||
* When calling tcp_abort() from a raw API TCP callback function,
|
||||
make sure you return ERR_ABRT to prevent accessing unallocated memory.
|
||||
(ERR_ABRT now means the applicaiton has called tcp_abort!)
|
||||
|
||||
+++ Netconn API:
|
||||
* Changed netconn_receive() and netconn_accept() to return
|
||||
err_t, not a pointer to new data/netconn.
|
||||
|
||||
+++ Socket API:
|
||||
* LWIP_SO_RCVTIMEO: when accept() or recv() time out, they
|
||||
now set errno to EWOULDBLOCK/EAGAIN, not ETIMEDOUT.
|
||||
|
||||
* Added a minimal version of posix fctl() to have a
|
||||
standardised way to set O_NONBLOCK for nonblocking sockets.
|
||||
|
||||
+++ all APIs:
|
||||
* correctly implemented SO(F)_REUSEADDR
|
||||
|
||||
++ Port changes
|
||||
|
||||
+++ new files:
|
||||
|
||||
* Added 4 new files: def.c, timers.c, timers.h, tcp_impl.h:
|
||||
|
||||
* Moved stack-internal parts of tcp.h to tcp_impl.h, tcp.h now only contains
|
||||
the actual application programmer's API
|
||||
|
||||
* Separated timer implementation from sys.h/.c, moved to timers.h/.c;
|
||||
Added timer implementation for NO_SYS==1, set NO_SYS_NO_TIMERS==1 if you
|
||||
still want to use your own timer implementation for NO_SYS==0 (as before).
|
||||
|
||||
+++ sys layer:
|
||||
|
||||
* Converted mbox- and semaphore-functions to take pointers to sys_mbox_t/
|
||||
sys_sem_t;
|
||||
|
||||
* Converted sys_mbox_new/sys_sem_new to take pointers and return err_t;
|
||||
|
||||
* Added Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX to let sys.h use
|
||||
binary semaphores instead of mutexes - as before)
|
||||
|
||||
+++ new options:
|
||||
|
||||
* Don't waste memory when chaining segments, added option TCP_OVERSIZE to
|
||||
prevent creating many small pbufs when calling tcp_write with many small
|
||||
blocks of data. Instead, pbufs are allocated larger than needed and the
|
||||
space is used for later calls to tcp_write.
|
||||
|
||||
* Added LWIP_NETIF_TX_SINGLE_PBUF to always copy to try to create single pbufs
|
||||
in tcp_write/udp_send.
|
||||
|
||||
* Added an additional option LWIP_ETHERNET to support ethernet without ARP
|
||||
(necessary for pure PPPoE)
|
||||
|
||||
* Add MEMP_SEPARATE_POOLS to place memory pools in separate arrays. This may
|
||||
be used to place these pools into user-defined memory by using external
|
||||
declaration.
|
||||
|
||||
* Added TCP_SNDQUEUELOWAT corresponding to TCP_SNDLOWAT
|
||||
|
||||
+++ new pools:
|
||||
|
||||
* Netdb uses a memp pool for allocating memory when getaddrinfo() is called,
|
||||
so MEMP_NUM_NETDB has to be set accordingly.
|
||||
|
||||
* DNS_LOCAL_HOSTLIST_IS_DYNAMIC uses a memp pool instead of the heap, so
|
||||
MEMP_NUM_LOCALHOSTLIST has to be set accordingly.
|
||||
|
||||
* Snmp-agent uses a memp pools instead of the heap, so MEMP_NUM_SNMP_* have
|
||||
to be set accordingly.
|
||||
|
||||
* PPPoE uses a MEMP pool instead of the heap, so MEMP_NUM_PPPOE_INTERFACES
|
||||
has to be set accordingly
|
||||
|
||||
* Integrated loopif into netif.c - loopif does not have to be created by the
|
||||
port any more, just define LWIP_HAVE_LOOPIF to 1.
|
||||
|
||||
* Added define LWIP_RAND() for lwip-wide randomization (needs to be defined
|
||||
in cc.h, e.g. used by igmp)
|
||||
|
||||
* Added printf-formatter X8_F to printf u8_t as hex
|
||||
|
||||
* The heap now may be moved to user-defined memory by defining
|
||||
LWIP_RAM_HEAP_POINTER as a void pointer to that memory's address
|
||||
|
||||
* added autoip_set_struct() and dhcp_set_struct() to let autoip and dhcp work
|
||||
with user-allocated structs instead of calling mem_malloc
|
||||
|
||||
* Added const char* name to mem- and memp-stats for easier debugging.
|
||||
|
||||
* Calculate the TCP/UDP checksum while copying to only fetch data once:
|
||||
Define LWIP_CHKSUM_COPY to a memcpy-like function that returns the checksum
|
||||
|
||||
* Added SO_REUSE_RXTOALL to pass received UDP broadcast/multicast packets to
|
||||
more than one pcb.
|
||||
|
||||
* Changed the semantics of ARP_QUEUEING==0: ARP_QUEUEING now cannot be turned
|
||||
off any more, if this is set to 0, only one packet (the most recent one) is
|
||||
queued (like demanded by RFC 1122).
|
||||
|
||||
|
||||
++ Major bugfixes/improvements
|
||||
|
||||
* Implemented tcp_shutdown() to only shut down one end of a connection
|
||||
* Implemented shutdown() at socket- and netconn-level
|
||||
* Added errorset support to select() + improved select speed overhead
|
||||
* Merged pppd to v2.3.11 (including some backported bugfixes from 2.4.x)
|
||||
* Added timer implementation for NO_SYS==1 (may be disabled with NO_SYS_NO_TIMERS==1
|
||||
* Use macros defined in ip_addr.h to work with IP addresses
|
||||
* Implemented many nonblocking socket/netconn functions
|
||||
* Fixed ARP input processing: only add a new entry if a request was directed as us
|
||||
* mem_realloc() to mem_trim() to prevent confusion with realloc()
|
||||
* Some improvements for AutoIP (don't route/forward link-local addresses, don't break
|
||||
existing connections when assigning a routable address)
|
||||
* Correctly handle remote side overrunning our rcv_wnd in ooseq case
|
||||
* Removed packing from ip_addr_t, the packed version is now only used in protocol headers
|
||||
* Corrected PBUF_POOL_BUFSIZE for ports where ETH_PAD_SIZE > 0
|
||||
* Added support for static ARP table entries
|
||||
|
||||
(STABLE-1.3.2)
|
||||
|
||||
* initial version of this file
|
||||
@@ -107,7 +107,7 @@ incoming connections or be explicitly connected to another host.
|
||||
Creates a new connection identifier (PCB). If memory is not
|
||||
available for creating the new pcb, NULL is returned.
|
||||
|
||||
- err_t tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr,
|
||||
- err_t tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr,
|
||||
u16_t port)
|
||||
|
||||
Binds the pcb to a local IP address and port number. The IP address
|
||||
@@ -147,6 +147,8 @@ incoming connections or be explicitly connected to another host.
|
||||
usually be called from the accept callback. This allows lwIP to perform
|
||||
housekeeping tasks, such as allowing further incoming connections to be
|
||||
queued in the listen backlog.
|
||||
ATTENTION: the PCB passed in must be the listening pcb, not the pcb passed
|
||||
into the accept callback!
|
||||
|
||||
- void tcp_accept(struct tcp_pcb *pcb,
|
||||
err_t (* accept)(void *arg, struct tcp_pcb *newpcb,
|
||||
@@ -154,8 +156,8 @@ incoming connections or be explicitly connected to another host.
|
||||
|
||||
Specified the callback function that should be called when a new
|
||||
connection arrives on a listening connection.
|
||||
|
||||
- err_t tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr,
|
||||
|
||||
- err_t tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr,
|
||||
u16_t port, err_t (* connected)(void *arg,
|
||||
struct tcp_pcb *tpcb,
|
||||
err_t err));
|
||||
@@ -176,7 +178,7 @@ incoming connections or be explicitly connected to another host.
|
||||
available for enqueueing the SYN segment. If the SYN indeed was
|
||||
enqueued successfully, the tcp_connect() function returns ERR_OK.
|
||||
|
||||
|
||||
|
||||
--- Sending TCP data
|
||||
|
||||
TCP data is sent by enqueueing the data with a call to
|
||||
@@ -184,15 +186,19 @@ tcp_write(). When the data is successfully transmitted to the remote
|
||||
host, the application will be notified with a call to a specified
|
||||
callback function.
|
||||
|
||||
- err_t tcp_write(struct tcp_pcb *pcb, void *dataptr, u16_t len,
|
||||
u8_t copy)
|
||||
- err_t tcp_write(struct tcp_pcb *pcb, const void *dataptr, u16_t len,
|
||||
u8_t apiflags)
|
||||
|
||||
Enqueues the data pointed to by the argument dataptr. The length of
|
||||
the data is passed as the len parameter. The copy argument is either
|
||||
0 or 1 and indicates whether the new memory should be allocated for
|
||||
the data to be copied into. If the argument is 0, no new memory
|
||||
should be allocated and the data should only be referenced by
|
||||
pointer.
|
||||
the data is passed as the len parameter. The apiflags can be one or more of:
|
||||
- TCP_WRITE_FLAG_COPY: indicates whether the new memory should be allocated
|
||||
for the data to be copied into. If this flag is not given, no new memory
|
||||
should be allocated and the data should only be referenced by pointer. This
|
||||
also means that the memory behind dataptr must not change until the data is
|
||||
ACKed by the remote host
|
||||
- TCP_WRITE_FLAG_MORE: indicates that more data follows. If this is given,
|
||||
the PSH flag is set in the last segment created by this call to tcp_write.
|
||||
If this flag is given, the PSH flag is not set.
|
||||
|
||||
The tcp_write() function will fail and return ERR_MEM if the length
|
||||
of the data exceeds the current send buffer size or if the length of
|
||||
@@ -238,7 +244,7 @@ window.
|
||||
|
||||
Must be called when the application has received the data. The len
|
||||
argument indicates the length of the received data.
|
||||
|
||||
|
||||
|
||||
--- Application polling
|
||||
|
||||
@@ -251,8 +257,9 @@ if a call to tcp_write() has failed because memory wasn't available,
|
||||
the application may use the polling functionality to call tcp_write()
|
||||
again when the connection has been idle for a while.
|
||||
|
||||
- void tcp_poll(struct tcp_pcb *pcb, u8_t interval,
|
||||
err_t (* poll)(void *arg, struct tcp_pcb *tpcb))
|
||||
- void tcp_poll(struct tcp_pcb *pcb,
|
||||
err_t (* poll)(void *arg, struct tcp_pcb *tpcb),
|
||||
u8_t interval)
|
||||
|
||||
Specifies the polling interval and the callback function that should
|
||||
be called to poll the application. The interval is specified in
|
||||
@@ -278,6 +285,11 @@ again when the connection has been idle for a while.
|
||||
Aborts the connection by sending a RST (reset) segment to the remote
|
||||
host. The pcb is deallocated. This function never fails.
|
||||
|
||||
ATTENTION: When calling this from one of the TCP callbacks, make
|
||||
sure you always return ERR_ABRT (and never return ERR_ABRT otherwise
|
||||
or you will risk accessing deallocated memory or memory leaks!
|
||||
|
||||
|
||||
If a connection is aborted because of an error, the application is
|
||||
alerted of this event by the err callback. Errors that might abort a
|
||||
connection are when there is a shortage of memory. The callback
|
||||
@@ -316,14 +328,14 @@ level of complexity of UDP, the interface is significantly simpler.
|
||||
|
||||
Removes and deallocates the pcb.
|
||||
|
||||
- err_t udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr,
|
||||
- err_t udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr,
|
||||
u16_t port)
|
||||
|
||||
Binds the pcb to a local address. The IP-address argument "ipaddr"
|
||||
can be IP_ADDR_ANY to indicate that it should listen to any local IP
|
||||
address. The function currently always return ERR_OK.
|
||||
|
||||
- err_t udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr,
|
||||
- err_t udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr,
|
||||
u16_t port)
|
||||
|
||||
Sets the remote end of the pcb. This function does not generate any
|
||||
@@ -341,7 +353,7 @@ level of complexity of UDP, the interface is significantly simpler.
|
||||
- void udp_recv(struct udp_pcb *pcb,
|
||||
void (* recv)(void *arg, struct udp_pcb *upcb,
|
||||
struct pbuf *p,
|
||||
struct ip_addr *addr,
|
||||
ip_addr_t *addr,
|
||||
u16_t port),
|
||||
void *recv_arg)
|
||||
|
||||
@@ -402,8 +414,8 @@ Call these functions in the order of appearance:
|
||||
Note: you must call tcp_fasttmr() and tcp_slowtmr() at the
|
||||
predefined regular intervals after this initialization.
|
||||
|
||||
- netif_add(struct netif *netif, struct ip_addr *ipaddr,
|
||||
struct ip_addr *netmask, struct ip_addr *gw,
|
||||
- netif_add(struct netif *netif, ip_addr_t *ipaddr,
|
||||
ip_addr_t *netmask, ip_addr_t *gw,
|
||||
void *state, err_t (* init)(struct netif *netif),
|
||||
err_t (* input)(struct pbuf *p, struct netif *netif))
|
||||
|
||||
@@ -476,3 +488,24 @@ to match your application and network.
|
||||
For a production release it is recommended to set LWIP_STATS to 0.
|
||||
Note that speed performance isn't influenced much by simply setting
|
||||
high values to the memory options.
|
||||
|
||||
For more optimization hints take a look at the lwIP wiki.
|
||||
|
||||
--- Zero-copy MACs
|
||||
|
||||
To achieve zero-copy on transmit, the data passed to the raw API must
|
||||
remain unchanged until sent. Because the send- (or write-)functions return
|
||||
when the packets have been enqueued for sending, data must be kept stable
|
||||
after that, too.
|
||||
|
||||
This implies that PBUF_RAM/PBUF_POOL pbufs passed to raw-API send functions
|
||||
must *not* be reused by the application unless their ref-count is 1.
|
||||
|
||||
For no-copy pbufs (PBUF_ROM/PBUF_REF), data must be kept unchanged, too,
|
||||
but the stack/driver will/must copy PBUF_REF'ed data when enqueueing, while
|
||||
PBUF_ROM-pbufs are just enqueued (as ROM-data is expected to never change).
|
||||
|
||||
Also, data passed to tcp_write without the copy-flag must not be changed!
|
||||
|
||||
Therefore, be careful which type of PBUF you use and if you copy TCP data
|
||||
or not!
|
||||
|
||||
@@ -46,7 +46,7 @@ Loading additional MIBs
|
||||
|
||||
Large SNMP message support
|
||||
The packet decoding and encoding routines are designed
|
||||
to use pbuf-chains. Larger payloads then the minimum
|
||||
to use pbuf-chains. Larger payloads than the minimum
|
||||
SNMP requirement of 484 octets are supported if the
|
||||
PBUF_POOL_SIZE and IP_REASS_BUFSIZE are set to match your
|
||||
local requirement.
|
||||
@@ -170,7 +170,7 @@ resembles the "auto-completion" operation)
|
||||
|
||||
The middle part is usually located in ROM (const)
|
||||
to preserve precious RAM on small microcontrollers.
|
||||
However RAM location is possible for an dynamically
|
||||
However RAM location is possible for a dynamically
|
||||
changing private tree.
|
||||
|
||||
The index part is handled by functions which in
|
||||
|
||||
@@ -34,26 +34,36 @@ in the sys_arch.h file. Mailboxes are equivalently represented by the
|
||||
type "sys_mbox_t". lwIP does not place any restrictions on how
|
||||
sys_sem_t or sys_mbox_t are represented internally.
|
||||
|
||||
Since lwIP 1.4.0, semaphore and mailbox functions are prototyped in a way that
|
||||
allows both using pointers or actual OS structures to be used. This way, memory
|
||||
required for such types can be either allocated in place (globally or on the
|
||||
stack) or on the heap (allocated internally in the "*_new()" functions).
|
||||
|
||||
The following functions must be implemented by the sys_arch:
|
||||
|
||||
- void sys_init(void)
|
||||
|
||||
Is called to initialize the sys_arch layer.
|
||||
|
||||
- sys_sem_t sys_sem_new(u8_t count)
|
||||
- err_t sys_sem_new(sys_sem_t *sem, u8_t count)
|
||||
|
||||
Creates and returns a new semaphore. The "count" argument specifies
|
||||
the initial state of the semaphore.
|
||||
Creates a new semaphore. The semaphore is allocated to the memory that 'sem'
|
||||
points to (which can be both a pointer or the actual OS structure).
|
||||
The "count" argument specifies the initial state of the semaphore (which is
|
||||
either 0 or 1).
|
||||
If the semaphore has been created, ERR_OK should be returned. Returning any
|
||||
other error will provide a hint what went wrong, but except for assertions,
|
||||
no real error handling is implemented.
|
||||
|
||||
- void sys_sem_free(sys_sem_t sem)
|
||||
- void sys_sem_free(sys_sem_t *sem)
|
||||
|
||||
Deallocates a semaphore.
|
||||
|
||||
- void sys_sem_signal(sys_sem_t sem)
|
||||
- void sys_sem_signal(sys_sem_t *sem)
|
||||
|
||||
Signals a semaphore.
|
||||
|
||||
- u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout)
|
||||
- u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
|
||||
|
||||
Blocks the thread while waiting for the semaphore to be
|
||||
signaled. If the "timeout" argument is non-zero, the thread should
|
||||
@@ -70,30 +80,47 @@ The following functions must be implemented by the sys_arch:
|
||||
Notice that lwIP implements a function with a similar name,
|
||||
sys_sem_wait(), that uses the sys_arch_sem_wait() function.
|
||||
|
||||
- sys_mbox_t sys_mbox_new(int size)
|
||||
- int sys_sem_valid(sys_sem_t *sem)
|
||||
|
||||
Returns 1 if the semaphore is valid, 0 if it is not valid.
|
||||
When using pointers, a simple way is to check the pointer for != NULL.
|
||||
When directly using OS structures, implementing this may be more complex.
|
||||
This may also be a define, in which case the function is not prototyped.
|
||||
|
||||
- void sys_sem_set_invalid(sys_sem_t *sem)
|
||||
|
||||
Invalidate a semaphore so that sys_sem_valid() returns 0.
|
||||
ATTENTION: This does NOT mean that the semaphore shall be deallocated:
|
||||
sys_sem_free() is always called before calling this function!
|
||||
This may also be a define, in which case the function is not prototyped.
|
||||
|
||||
- err_t sys_mbox_new(sys_mbox_t *mbox, int size)
|
||||
|
||||
Creates an empty mailbox for maximum "size" elements. Elements stored
|
||||
in mailboxes are pointers. You have to define macros "_MBOX_SIZE"
|
||||
in your lwipopts.h, or ignore this parameter in your implementation
|
||||
and use a default size.
|
||||
If the mailbox has been created, ERR_OK should be returned. Returning any
|
||||
other error will provide a hint what went wrong, but except for assertions,
|
||||
no real error handling is implemented.
|
||||
|
||||
- void sys_mbox_free(sys_mbox_t mbox)
|
||||
- void sys_mbox_free(sys_mbox_t *mbox)
|
||||
|
||||
Deallocates a mailbox. If there are messages still present in the
|
||||
mailbox when the mailbox is deallocated, it is an indication of a
|
||||
programming error in lwIP and the developer should be notified.
|
||||
|
||||
- void sys_mbox_post(sys_mbox_t mbox, void *msg)
|
||||
- void sys_mbox_post(sys_mbox_t *mbox, void *msg)
|
||||
|
||||
Posts the "msg" to the mailbox. This function have to block until
|
||||
the "msg" is really posted.
|
||||
|
||||
- err_t sys_mbox_trypost(sys_mbox_t mbox, void *msg)
|
||||
- err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
|
||||
|
||||
Try to post the "msg" to the mailbox. Returns ERR_MEM if this one
|
||||
is full, else, ERR_OK if the "msg" is posted.
|
||||
|
||||
- u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout)
|
||||
- u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
|
||||
|
||||
Blocks the thread until a message arrives in the mailbox, but does
|
||||
not block the thread longer than "timeout" milliseconds (similar to
|
||||
@@ -110,7 +137,7 @@ The following functions must be implemented by the sys_arch:
|
||||
Note that a function with a similar name, sys_mbox_fetch(), is
|
||||
implemented by lwIP.
|
||||
|
||||
- u32_t sys_arch_mbox_tryfetch(sys_mbox_t mbox, void **msg)
|
||||
- u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
|
||||
|
||||
This is similar to sys_arch_mbox_fetch, however if a message is not
|
||||
present in the mailbox, it immediately returns with the code
|
||||
@@ -122,19 +149,21 @@ The following functions must be implemented by the sys_arch:
|
||||
#define sys_arch_mbox_tryfetch(mbox,msg) \
|
||||
sys_arch_mbox_fetch(mbox,msg,1)
|
||||
although this would introduce unnecessary delays.
|
||||
|
||||
- struct sys_timeouts *sys_arch_timeouts(void)
|
||||
|
||||
Returns a pointer to the per-thread sys_timeouts structure. In lwIP,
|
||||
each thread has a list of timeouts which is repressented as a linked
|
||||
list of sys_timeout structures. The sys_timeouts structure holds a
|
||||
pointer to a linked list of timeouts. This function is called by
|
||||
the lwIP timeout scheduler and must not return a NULL value.
|
||||
- int sys_mbox_valid(sys_mbox_t *mbox)
|
||||
|
||||
Returns 1 if the mailbox is valid, 0 if it is not valid.
|
||||
When using pointers, a simple way is to check the pointer for != NULL.
|
||||
When directly using OS structures, implementing this may be more complex.
|
||||
This may also be a define, in which case the function is not prototyped.
|
||||
|
||||
- void sys_mbox_set_invalid(sys_mbox_t *mbox)
|
||||
|
||||
Invalidate a mailbox so that sys_mbox_valid() returns 0.
|
||||
ATTENTION: This does NOT mean that the mailbox shall be deallocated:
|
||||
sys_mbox_free() is always called before calling this function!
|
||||
This may also be a define, in which case the function is not prototyped.
|
||||
|
||||
In a single thread sys_arch implementation, this function will
|
||||
simply return a pointer to a global sys_timeouts variable stored in
|
||||
the sys_arch module.
|
||||
|
||||
If threads are supported by the underlying operating system and if
|
||||
such functionality is needed in lwIP, the following function will have
|
||||
to be implemented as well:
|
||||
@@ -168,6 +197,16 @@ to be implemented as well:
|
||||
more information. This function is only required if your port is supporting
|
||||
an operating system.
|
||||
|
||||
For some configurations, you also need:
|
||||
|
||||
- u32_t sys_now(void)
|
||||
|
||||
This optional function returns the current time in milliseconds (don't care
|
||||
for wraparound, this is only used for time diffs).
|
||||
Not implementing this function means you cannot use some modules (e.g. TCP
|
||||
timestamps, internal timeouts for NO_SYS==1).
|
||||
|
||||
|
||||
Note:
|
||||
|
||||
Be carefull with using mem_malloc() in sys_arch. When malloc() refers to
|
||||
|
||||
@@ -71,19 +71,19 @@ netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_cal
|
||||
struct api_msg msg;
|
||||
|
||||
conn = netconn_alloc(t, callback);
|
||||
if (conn != NULL ) {
|
||||
if (conn != NULL) {
|
||||
msg.function = do_newconn;
|
||||
msg.msg.msg.n.proto = proto;
|
||||
msg.msg.conn = conn;
|
||||
TCPIP_APIMSG(&msg);
|
||||
|
||||
if (conn->err != ERR_OK) {
|
||||
if (TCPIP_APIMSG(&msg) != ERR_OK) {
|
||||
LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL);
|
||||
LWIP_ASSERT("conn has no op_completed", conn->op_completed != SYS_SEM_NULL);
|
||||
LWIP_ASSERT("conn has no recvmbox", conn->recvmbox != SYS_MBOX_NULL);
|
||||
LWIP_ASSERT("conn->acceptmbox shouldn't exist", conn->acceptmbox == SYS_MBOX_NULL);
|
||||
sys_sem_free(conn->op_completed);
|
||||
sys_mbox_free(conn->recvmbox);
|
||||
LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed));
|
||||
LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox));
|
||||
#if LWIP_TCP
|
||||
LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox));
|
||||
#endif /* LWIP_TCP */
|
||||
sys_sem_free(&conn->op_completed);
|
||||
sys_mbox_free(&conn->recvmbox);
|
||||
memp_free(MEMP_NETCONN, conn);
|
||||
return NULL;
|
||||
}
|
||||
@@ -113,9 +113,10 @@ netconn_delete(struct netconn *conn)
|
||||
msg.msg.conn = conn;
|
||||
tcpip_apimsg(&msg);
|
||||
|
||||
conn->pcb.tcp = NULL;
|
||||
netconn_free(conn);
|
||||
|
||||
/* don't care for return value of do_delconn since it only calls void functions */
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
@@ -131,9 +132,10 @@ netconn_delete(struct netconn *conn)
|
||||
* ERR_OK if the information was retrieved
|
||||
*/
|
||||
err_t
|
||||
netconn_getaddr(struct netconn *conn, struct ip_addr *addr, u16_t *port, u8_t local)
|
||||
netconn_getaddr(struct netconn *conn, ip_addr_t *addr, u16_t *port, u8_t local)
|
||||
{
|
||||
struct api_msg msg;
|
||||
err_t err;
|
||||
|
||||
LWIP_ERROR("netconn_getaddr: invalid conn", (conn != NULL), return ERR_ARG;);
|
||||
LWIP_ERROR("netconn_getaddr: invalid addr", (addr != NULL), return ERR_ARG;);
|
||||
@@ -144,9 +146,10 @@ netconn_getaddr(struct netconn *conn, struct ip_addr *addr, u16_t *port, u8_t lo
|
||||
msg.msg.msg.ad.ipaddr = addr;
|
||||
msg.msg.msg.ad.port = port;
|
||||
msg.msg.msg.ad.local = local;
|
||||
TCPIP_APIMSG(&msg);
|
||||
err = TCPIP_APIMSG(&msg);
|
||||
|
||||
return conn->err;
|
||||
NETCONN_SET_SAFE_ERR(conn, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -160,9 +163,10 @@ netconn_getaddr(struct netconn *conn, struct ip_addr *addr, u16_t *port, u8_t lo
|
||||
* @return ERR_OK if bound, any other err_t on failure
|
||||
*/
|
||||
err_t
|
||||
netconn_bind(struct netconn *conn, struct ip_addr *addr, u16_t port)
|
||||
netconn_bind(struct netconn *conn, ip_addr_t *addr, u16_t port)
|
||||
{
|
||||
struct api_msg msg;
|
||||
err_t err;
|
||||
|
||||
LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;);
|
||||
|
||||
@@ -170,8 +174,10 @@ netconn_bind(struct netconn *conn, struct ip_addr *addr, u16_t port)
|
||||
msg.msg.conn = conn;
|
||||
msg.msg.msg.bc.ipaddr = addr;
|
||||
msg.msg.msg.bc.port = port;
|
||||
TCPIP_APIMSG(&msg);
|
||||
return conn->err;
|
||||
err = TCPIP_APIMSG(&msg);
|
||||
|
||||
NETCONN_SET_SAFE_ERR(conn, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,9 +189,10 @@ netconn_bind(struct netconn *conn, struct ip_addr *addr, u16_t port)
|
||||
* @return ERR_OK if connected, return value of tcp_/udp_/raw_connect otherwise
|
||||
*/
|
||||
err_t
|
||||
netconn_connect(struct netconn *conn, struct ip_addr *addr, u16_t port)
|
||||
netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port)
|
||||
{
|
||||
struct api_msg msg;
|
||||
err_t err;
|
||||
|
||||
LWIP_ERROR("netconn_connect: invalid conn", (conn != NULL), return ERR_ARG;);
|
||||
|
||||
@@ -194,8 +201,10 @@ netconn_connect(struct netconn *conn, struct ip_addr *addr, u16_t port)
|
||||
msg.msg.msg.bc.ipaddr = addr;
|
||||
msg.msg.msg.bc.port = port;
|
||||
/* This is the only function which need to not block tcpip_thread */
|
||||
tcpip_apimsg(&msg);
|
||||
return conn->err;
|
||||
err = tcpip_apimsg(&msg);
|
||||
|
||||
NETCONN_SET_SAFE_ERR(conn, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -208,13 +217,16 @@ err_t
|
||||
netconn_disconnect(struct netconn *conn)
|
||||
{
|
||||
struct api_msg msg;
|
||||
err_t err;
|
||||
|
||||
LWIP_ERROR("netconn_disconnect: invalid conn", (conn != NULL), return ERR_ARG;);
|
||||
|
||||
msg.function = do_disconnect;
|
||||
msg.msg.conn = conn;
|
||||
TCPIP_APIMSG(&msg);
|
||||
return conn->err;
|
||||
err = TCPIP_APIMSG(&msg);
|
||||
|
||||
NETCONN_SET_SAFE_ERR(conn, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -228,7 +240,9 @@ netconn_disconnect(struct netconn *conn)
|
||||
err_t
|
||||
netconn_listen_with_backlog(struct netconn *conn, u8_t backlog)
|
||||
{
|
||||
#if LWIP_TCP
|
||||
struct api_msg msg;
|
||||
err_t err;
|
||||
|
||||
/* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */
|
||||
LWIP_UNUSED_ARG(backlog);
|
||||
@@ -240,156 +254,285 @@ netconn_listen_with_backlog(struct netconn *conn, u8_t backlog)
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
msg.msg.msg.lb.backlog = backlog;
|
||||
#endif /* TCP_LISTEN_BACKLOG */
|
||||
TCPIP_APIMSG(&msg);
|
||||
return conn->err;
|
||||
err = TCPIP_APIMSG(&msg);
|
||||
|
||||
NETCONN_SET_SAFE_ERR(conn, err);
|
||||
return err;
|
||||
#else /* LWIP_TCP */
|
||||
LWIP_UNUSED_ARG(conn);
|
||||
LWIP_UNUSED_ARG(backlog);
|
||||
return ERR_ARG;
|
||||
#endif /* LWIP_TCP */
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept a new connection on a TCP listening netconn.
|
||||
*
|
||||
* @param conn the TCP listen netconn
|
||||
* @return the newly accepted netconn or NULL on timeout
|
||||
* @param new_conn pointer where the new connection is stored
|
||||
* @return ERR_OK if a new connection has been received or an error
|
||||
* code otherwise
|
||||
*/
|
||||
struct netconn *
|
||||
netconn_accept(struct netconn *conn)
|
||||
err_t
|
||||
netconn_accept(struct netconn *conn, struct netconn **new_conn)
|
||||
{
|
||||
#if LWIP_TCP
|
||||
struct netconn *newconn;
|
||||
|
||||
LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return NULL;);
|
||||
LWIP_ERROR("netconn_accept: invalid acceptmbox", (conn->acceptmbox != SYS_MBOX_NULL), return NULL;);
|
||||
|
||||
#if LWIP_SO_RCVTIMEO
|
||||
if (sys_arch_mbox_fetch(conn->acceptmbox, (void *)&newconn, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
|
||||
newconn = NULL;
|
||||
} else
|
||||
#else
|
||||
sys_arch_mbox_fetch(conn->acceptmbox, (void *)&newconn, 0);
|
||||
#endif /* LWIP_SO_RCVTIMEO*/
|
||||
{
|
||||
/* Register event with callback */
|
||||
API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
|
||||
|
||||
err_t err;
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
if (newconn != NULL) {
|
||||
/* Let the stack know that we have accepted the connection. */
|
||||
struct api_msg msg;
|
||||
msg.function = do_recv;
|
||||
msg.msg.conn = conn;
|
||||
TCPIP_APIMSG(&msg);
|
||||
}
|
||||
struct api_msg msg;
|
||||
#endif /* TCP_LISTEN_BACKLOG */
|
||||
|
||||
LWIP_ERROR("netconn_accept: invalid pointer", (new_conn != NULL), return ERR_ARG;);
|
||||
*new_conn = NULL;
|
||||
LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;);
|
||||
LWIP_ERROR("netconn_accept: invalid acceptmbox", sys_mbox_valid(&conn->acceptmbox), return ERR_ARG;);
|
||||
|
||||
err = conn->last_err;
|
||||
if (ERR_IS_FATAL(err)) {
|
||||
/* don't recv on fatal errors: this might block the application task
|
||||
waiting on acceptmbox forever! */
|
||||
return err;
|
||||
}
|
||||
|
||||
return newconn;
|
||||
#if LWIP_SO_RCVTIMEO
|
||||
if (sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
|
||||
NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT);
|
||||
return ERR_TIMEOUT;
|
||||
}
|
||||
#else
|
||||
sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, 0);
|
||||
#endif /* LWIP_SO_RCVTIMEO*/
|
||||
/* Register event with callback */
|
||||
API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
|
||||
|
||||
if (newconn == NULL) {
|
||||
/* connection has been aborted */
|
||||
NETCONN_SET_SAFE_ERR(conn, ERR_ABRT);
|
||||
return ERR_ABRT;
|
||||
}
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
/* Let the stack know that we have accepted the connection. */
|
||||
msg.function = do_recv;
|
||||
msg.msg.conn = conn;
|
||||
/* don't care for the return value of do_recv */
|
||||
TCPIP_APIMSG(&msg);
|
||||
#endif /* TCP_LISTEN_BACKLOG */
|
||||
|
||||
*new_conn = newconn;
|
||||
/* don't set conn->last_err: it's only ERR_OK, anyway */
|
||||
return ERR_OK;
|
||||
#else /* LWIP_TCP */
|
||||
LWIP_UNUSED_ARG(conn);
|
||||
LWIP_UNUSED_ARG(new_conn);
|
||||
return ERR_ARG;
|
||||
#endif /* LWIP_TCP */
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive data: actual implementation that doesn't care whether pbuf or netbuf
|
||||
* is received
|
||||
*
|
||||
* @param conn the netconn from which to receive data
|
||||
* @param new_buf pointer where a new pbuf/netbuf is stored when received data
|
||||
* @return ERR_OK if data has been received, an error code otherwise (timeout,
|
||||
* memory error or another error)
|
||||
*/
|
||||
static err_t
|
||||
netconn_recv_data(struct netconn *conn, void **new_buf)
|
||||
{
|
||||
void *buf = NULL;
|
||||
u16_t len;
|
||||
err_t err;
|
||||
#if LWIP_TCP
|
||||
struct api_msg msg;
|
||||
#endif /* LWIP_TCP */
|
||||
|
||||
LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;);
|
||||
*new_buf = NULL;
|
||||
LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;);
|
||||
LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;);
|
||||
|
||||
err = conn->last_err;
|
||||
if (ERR_IS_FATAL(err)) {
|
||||
/* don't recv on fatal errors: this might block the application task
|
||||
waiting on recvmbox forever! */
|
||||
/* @todo: this does not allow us to fetch data that has been put into recvmbox
|
||||
before the fatal error occurred - is that a problem? */
|
||||
return err;
|
||||
}
|
||||
|
||||
#if LWIP_SO_RCVTIMEO
|
||||
if (sys_arch_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
|
||||
NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT);
|
||||
return ERR_TIMEOUT;
|
||||
}
|
||||
#else
|
||||
sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0);
|
||||
#endif /* LWIP_SO_RCVTIMEO*/
|
||||
|
||||
#if LWIP_TCP
|
||||
#if (LWIP_UDP || LWIP_RAW)
|
||||
if (conn->type == NETCONN_TCP)
|
||||
#endif /* (LWIP_UDP || LWIP_RAW) */
|
||||
{
|
||||
if (!netconn_get_noautorecved(conn) || (buf == NULL)) {
|
||||
/* Let the stack know that we have taken the data. */
|
||||
/* TODO: Speedup: Don't block and wait for the answer here
|
||||
(to prevent multiple thread-switches). */
|
||||
msg.function = do_recv;
|
||||
msg.msg.conn = conn;
|
||||
if (buf != NULL) {
|
||||
msg.msg.msg.r.len = ((struct pbuf *)buf)->tot_len;
|
||||
} else {
|
||||
msg.msg.msg.r.len = 1;
|
||||
}
|
||||
/* don't care for the return value of do_recv */
|
||||
TCPIP_APIMSG(&msg);
|
||||
}
|
||||
|
||||
/* If we are closed, we indicate that we no longer wish to use the socket */
|
||||
if (buf == NULL) {
|
||||
API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);
|
||||
/* Avoid to lose any previous error code */
|
||||
NETCONN_SET_SAFE_ERR(conn, ERR_CLSD);
|
||||
return ERR_CLSD;
|
||||
}
|
||||
len = ((struct pbuf *)buf)->tot_len;
|
||||
}
|
||||
#endif /* LWIP_TCP */
|
||||
#if LWIP_TCP && (LWIP_UDP || LWIP_RAW)
|
||||
else
|
||||
#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */
|
||||
#if (LWIP_UDP || LWIP_RAW)
|
||||
{
|
||||
LWIP_ASSERT("buf != NULL", buf != NULL);
|
||||
len = netbuf_len((struct netbuf *)buf);
|
||||
}
|
||||
#endif /* (LWIP_UDP || LWIP_RAW) */
|
||||
|
||||
#if LWIP_SO_RCVBUF
|
||||
SYS_ARCH_DEC(conn->recv_avail, len);
|
||||
#endif /* LWIP_SO_RCVBUF */
|
||||
/* Register event with callback */
|
||||
API_EVENT(conn, NETCONN_EVT_RCVMINUS, len);
|
||||
|
||||
LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv_data: received %p, len=%"U16_F"\n", buf, len));
|
||||
|
||||
*new_buf = buf;
|
||||
/* don't set conn->last_err: it's only ERR_OK, anyway */
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive data (in form of a pbuf) from a TCP netconn
|
||||
*
|
||||
* @param conn the netconn from which to receive data
|
||||
* @param new_buf pointer where a new pbuf is stored when received data
|
||||
* @return ERR_OK if data has been received, an error code otherwise (timeout,
|
||||
* memory error or another error)
|
||||
* ERR_ARG if conn is not a TCP netconn
|
||||
*/
|
||||
err_t
|
||||
netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf)
|
||||
{
|
||||
LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL) &&
|
||||
netconn_type(conn) == NETCONN_TCP, return ERR_ARG;);
|
||||
|
||||
return netconn_recv_data(conn, (void **)new_buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive data (in form of a netbuf containing a packet buffer) from a netconn
|
||||
*
|
||||
* @param conn the netconn from which to receive data
|
||||
* @return a new netbuf containing received data or NULL on memory error or timeout
|
||||
* @param new_buf pointer where a new netbuf is stored when received data
|
||||
* @return ERR_OK if data has been received, an error code otherwise (timeout,
|
||||
* memory error or another error)
|
||||
*/
|
||||
struct netbuf *
|
||||
netconn_recv(struct netconn *conn)
|
||||
err_t
|
||||
netconn_recv(struct netconn *conn, struct netbuf **new_buf)
|
||||
{
|
||||
struct api_msg msg;
|
||||
struct netbuf *buf = NULL;
|
||||
struct pbuf *p;
|
||||
u16_t len;
|
||||
|
||||
LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return NULL;);
|
||||
|
||||
if (conn->recvmbox == SYS_MBOX_NULL) {
|
||||
/* @todo: should calling netconn_recv on a TCP listen conn be fatal (ERR_CONN)?? */
|
||||
/* TCP listen conns don't have a recvmbox! */
|
||||
conn->err = ERR_CONN;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ERR_IS_FATAL(conn->err)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (conn->type == NETCONN_TCP) {
|
||||
#if LWIP_TCP
|
||||
if (conn->state == NETCONN_LISTEN) {
|
||||
/* @todo: should calling netconn_recv on a TCP listen conn be fatal?? */
|
||||
conn->err = ERR_CONN;
|
||||
return NULL;
|
||||
}
|
||||
struct netbuf *buf = NULL;
|
||||
err_t err;
|
||||
#endif /* LWIP_TCP */
|
||||
|
||||
buf = memp_malloc(MEMP_NETBUF);
|
||||
LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;);
|
||||
*new_buf = NULL;
|
||||
LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;);
|
||||
LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;);
|
||||
|
||||
#if LWIP_TCP
|
||||
#if (LWIP_UDP || LWIP_RAW)
|
||||
if (conn->type == NETCONN_TCP)
|
||||
#endif /* (LWIP_UDP || LWIP_RAW) */
|
||||
{
|
||||
struct pbuf *p = NULL;
|
||||
/* This is not a listening netconn, since recvmbox is set */
|
||||
|
||||
buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
|
||||
if (buf == NULL) {
|
||||
conn->err = ERR_MEM;
|
||||
return NULL;
|
||||
NETCONN_SET_SAFE_ERR(conn, ERR_MEM);
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
#if LWIP_SO_RCVTIMEO
|
||||
if (sys_arch_mbox_fetch(conn->recvmbox, (void *)&p, conn->recv_timeout)==SYS_ARCH_TIMEOUT) {
|
||||
err = netconn_recv_data(conn, (void **)&p);
|
||||
if (err != ERR_OK) {
|
||||
memp_free(MEMP_NETBUF, buf);
|
||||
conn->err = ERR_TIMEOUT;
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
sys_arch_mbox_fetch(conn->recvmbox, (void *)&p, 0);
|
||||
#endif /* LWIP_SO_RCVTIMEO*/
|
||||
|
||||
if (p != NULL) {
|
||||
len = p->tot_len;
|
||||
SYS_ARCH_DEC(conn->recv_avail, len);
|
||||
} else {
|
||||
len = 0;
|
||||
}
|
||||
|
||||
/* Register event with callback */
|
||||
API_EVENT(conn, NETCONN_EVT_RCVMINUS, len);
|
||||
|
||||
/* If we are closed, we indicate that we no longer wish to use the socket */
|
||||
if (p == NULL) {
|
||||
memp_free(MEMP_NETBUF, buf);
|
||||
/* Avoid to lose any previous error code */
|
||||
if (conn->err == ERR_OK) {
|
||||
conn->err = ERR_CLSD;
|
||||
}
|
||||
return NULL;
|
||||
return err;
|
||||
}
|
||||
LWIP_ASSERT("p != NULL", p != NULL);
|
||||
|
||||
buf->p = p;
|
||||
buf->ptr = p;
|
||||
buf->port = 0;
|
||||
buf->addr = NULL;
|
||||
|
||||
/* Let the stack know that we have taken the data. */
|
||||
msg.function = do_recv;
|
||||
msg.msg.conn = conn;
|
||||
if (buf != NULL) {
|
||||
msg.msg.msg.r.len = buf->p->tot_len;
|
||||
} else {
|
||||
msg.msg.msg.r.len = 1;
|
||||
}
|
||||
TCPIP_APIMSG(&msg);
|
||||
ip_addr_set_any(&buf->addr);
|
||||
*new_buf = buf;
|
||||
/* don't set conn->last_err: it's only ERR_OK, anyway */
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif /* LWIP_TCP */
|
||||
} else {
|
||||
#if LWIP_TCP && (LWIP_UDP || LWIP_RAW)
|
||||
else
|
||||
#endif /* LWIP_TCP && (LWIP_UDP || LWIP_RAW) */
|
||||
{
|
||||
#if (LWIP_UDP || LWIP_RAW)
|
||||
#if LWIP_SO_RCVTIMEO
|
||||
if (sys_arch_mbox_fetch(conn->recvmbox, (void *)&buf, conn->recv_timeout)==SYS_ARCH_TIMEOUT) {
|
||||
buf = NULL;
|
||||
}
|
||||
#else
|
||||
sys_arch_mbox_fetch(conn->recvmbox, (void *)&buf, 0);
|
||||
#endif /* LWIP_SO_RCVTIMEO*/
|
||||
if (buf!=NULL) {
|
||||
SYS_ARCH_DEC(conn->recv_avail, buf->p->tot_len);
|
||||
/* Register event with callback */
|
||||
API_EVENT(conn, NETCONN_EVT_RCVMINUS, buf->p->tot_len);
|
||||
}
|
||||
return netconn_recv_data(conn, (void **)new_buf);
|
||||
#endif /* (LWIP_UDP || LWIP_RAW) */
|
||||
}
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv: received %p (err %d)\n", (void *)buf, conn->err));
|
||||
|
||||
return buf;
|
||||
/**
|
||||
* TCP: update the receive window: by calling this, the application
|
||||
* tells the stack that it has processed data and is able to accept
|
||||
* new data.
|
||||
* ATTENTION: use with care, this is mainly used for sockets!
|
||||
* Can only be used when calling netconn_set_noautorecved(conn, 1) before.
|
||||
*
|
||||
* @param conn the netconn for which to update the receive window
|
||||
* @param length amount of data processed (ATTENTION: this must be accurate!)
|
||||
*/
|
||||
void
|
||||
netconn_recved(struct netconn *conn, u32_t length)
|
||||
{
|
||||
#if LWIP_TCP
|
||||
if ((conn != NULL) && (conn->type == NETCONN_TCP) &&
|
||||
(netconn_get_noautorecved(conn))) {
|
||||
struct api_msg msg;
|
||||
/* Let the stack know that we have taken the data. */
|
||||
/* TODO: Speedup: Don't block and wait for the answer here
|
||||
(to prevent multiple thread-switches). */
|
||||
msg.function = do_recv;
|
||||
msg.msg.conn = conn;
|
||||
msg.msg.msg.r.len = length;
|
||||
/* don't care for the return value of do_recv */
|
||||
TCPIP_APIMSG(&msg);
|
||||
}
|
||||
#else /* LWIP_TCP */
|
||||
LWIP_UNUSED_ARG(conn);
|
||||
LWIP_UNUSED_ARG(length);
|
||||
#endif /* LWIP_TCP */
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -403,10 +546,10 @@ netconn_recv(struct netconn *conn)
|
||||
* @return ERR_OK if data was sent, any other err_t on error
|
||||
*/
|
||||
err_t
|
||||
netconn_sendto(struct netconn *conn, struct netbuf *buf, struct ip_addr *addr, u16_t port)
|
||||
netconn_sendto(struct netconn *conn, struct netbuf *buf, ip_addr_t *addr, u16_t port)
|
||||
{
|
||||
if (buf != NULL) {
|
||||
buf->addr = addr;
|
||||
ip_addr_set(&buf->addr, addr);
|
||||
buf->port = port;
|
||||
return netconn_send(conn, buf);
|
||||
}
|
||||
@@ -424,6 +567,7 @@ err_t
|
||||
netconn_send(struct netconn *conn, struct netbuf *buf)
|
||||
{
|
||||
struct api_msg msg;
|
||||
err_t err;
|
||||
|
||||
LWIP_ERROR("netconn_send: invalid conn", (conn != NULL), return ERR_ARG;);
|
||||
|
||||
@@ -431,8 +575,10 @@ netconn_send(struct netconn *conn, struct netbuf *buf)
|
||||
msg.function = do_send;
|
||||
msg.msg.conn = conn;
|
||||
msg.msg.msg.b = buf;
|
||||
TCPIP_APIMSG(&msg);
|
||||
return conn->err;
|
||||
err = TCPIP_APIMSG(&msg);
|
||||
|
||||
NETCONN_SET_SAFE_ERR(conn, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -442,28 +588,95 @@ netconn_send(struct netconn *conn, struct netbuf *buf)
|
||||
* @param dataptr pointer to the application buffer that contains the data to send
|
||||
* @param size size of the application data to send
|
||||
* @param apiflags combination of following flags :
|
||||
* - NETCONN_COPY (0x01) data will be copied into memory belonging to the stack
|
||||
* - NETCONN_MORE (0x02) for TCP connection, PSH flag will be set on last segment sent
|
||||
* - NETCONN_COPY: data will be copied into memory belonging to the stack
|
||||
* - NETCONN_MORE: for TCP connection, PSH flag will be set on last segment sent
|
||||
* - NETCONN_DONTBLOCK: only write the data if all dat can be written at once
|
||||
* @param bytes_written pointer to a location that receives the number of written bytes
|
||||
* @return ERR_OK if data was sent, any other err_t on error
|
||||
*/
|
||||
err_t
|
||||
netconn_write(struct netconn *conn, const void *dataptr, size_t size, u8_t apiflags)
|
||||
netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size,
|
||||
u8_t apiflags, size_t *bytes_written)
|
||||
{
|
||||
struct api_msg msg;
|
||||
err_t err;
|
||||
u8_t dontblock;
|
||||
|
||||
LWIP_ERROR("netconn_write: invalid conn", (conn != NULL), return ERR_ARG;);
|
||||
LWIP_ERROR("netconn_write: invalid conn->type", (conn->type == NETCONN_TCP), return ERR_VAL;);
|
||||
if (size == 0) {
|
||||
return ERR_OK;
|
||||
}
|
||||
dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK);
|
||||
if (dontblock && !bytes_written) {
|
||||
/* This implies netconn_write() cannot be used for non-blocking send, since
|
||||
it has no way to return the number of bytes written. */
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
/* non-blocking write sends as much */
|
||||
msg.function = do_write;
|
||||
msg.msg.conn = conn;
|
||||
msg.msg.msg.w.dataptr = dataptr;
|
||||
msg.msg.msg.w.apiflags = apiflags;
|
||||
msg.msg.msg.w.len = size;
|
||||
#if LWIP_SO_SNDTIMEO
|
||||
if (conn->send_timeout != 0) {
|
||||
/* get the time we started, which is later compared to
|
||||
sys_now() + conn->send_timeout */
|
||||
msg.msg.msg.w.time_started = sys_now();
|
||||
} else {
|
||||
msg.msg.msg.w.time_started = 0;
|
||||
}
|
||||
#endif /* LWIP_SO_SNDTIMEO */
|
||||
|
||||
/* For locking the core: this _can_ be delayed on low memory/low send buffer,
|
||||
but if it is, this is done inside api_msg.c:do_write(), so we can use the
|
||||
non-blocking version here. */
|
||||
TCPIP_APIMSG(&msg);
|
||||
return conn->err;
|
||||
err = TCPIP_APIMSG(&msg);
|
||||
if ((err == ERR_OK) && (bytes_written != NULL)) {
|
||||
if (dontblock
|
||||
#if LWIP_SO_SNDTIMEO
|
||||
|| (conn->send_timeout != 0)
|
||||
#endif /* LWIP_SO_SNDTIMEO */
|
||||
) {
|
||||
/* nonblocking write: maybe the data has been sent partly */
|
||||
*bytes_written = msg.msg.msg.w.len;
|
||||
} else {
|
||||
/* blocking call succeeded: all data has been sent if it */
|
||||
*bytes_written = size;
|
||||
}
|
||||
}
|
||||
|
||||
NETCONN_SET_SAFE_ERR(conn, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close ot shutdown a TCP netconn (doesn't delete it).
|
||||
*
|
||||
* @param conn the TCP netconn to close or shutdown
|
||||
* @param how fully close or only shutdown one side?
|
||||
* @return ERR_OK if the netconn was closed, any other err_t on error
|
||||
*/
|
||||
static err_t
|
||||
netconn_close_shutdown(struct netconn *conn, u8_t how)
|
||||
{
|
||||
struct api_msg msg;
|
||||
err_t err;
|
||||
|
||||
LWIP_ERROR("netconn_close: invalid conn", (conn != NULL), return ERR_ARG;);
|
||||
|
||||
msg.function = do_close;
|
||||
msg.msg.conn = conn;
|
||||
/* shutting down both ends is the same as closing */
|
||||
msg.msg.msg.sd.shut = how;
|
||||
/* because of the LWIP_TCPIP_CORE_LOCKING implementation of do_close,
|
||||
don't use TCPIP_APIMSG here */
|
||||
err = tcpip_apimsg(&msg);
|
||||
|
||||
NETCONN_SET_SAFE_ERR(conn, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -475,14 +688,20 @@ netconn_write(struct netconn *conn, const void *dataptr, size_t size, u8_t apifl
|
||||
err_t
|
||||
netconn_close(struct netconn *conn)
|
||||
{
|
||||
struct api_msg msg;
|
||||
/* shutting down both ends is the same as closing */
|
||||
return netconn_close_shutdown(conn, NETCONN_SHUT_RDWR);
|
||||
}
|
||||
|
||||
LWIP_ERROR("netconn_close: invalid conn", (conn != NULL), return ERR_ARG;);
|
||||
|
||||
msg.function = do_close;
|
||||
msg.msg.conn = conn;
|
||||
tcpip_apimsg(&msg);
|
||||
return conn->err;
|
||||
/**
|
||||
* Shut down one or both sides of a TCP netconn (doesn't delete it).
|
||||
*
|
||||
* @param conn the TCP netconn to shut down
|
||||
* @return ERR_OK if the netconn was closed, any other err_t on error
|
||||
*/
|
||||
err_t
|
||||
netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx)
|
||||
{
|
||||
return netconn_close_shutdown(conn, (shut_rx ? NETCONN_SHUT_RD : 0) | (shut_tx ? NETCONN_SHUT_WR : 0));
|
||||
}
|
||||
|
||||
#if LWIP_IGMP
|
||||
@@ -491,28 +710,31 @@ netconn_close(struct netconn *conn)
|
||||
*
|
||||
* @param conn the UDP netconn for which to change multicast addresses
|
||||
* @param multiaddr IP address of the multicast group to join or leave
|
||||
* @param interface the IP address of the network interface on which to send
|
||||
* @param netif_addr the IP address of the network interface on which to send
|
||||
* the igmp message
|
||||
* @param join_or_leave flag whether to send a join- or leave-message
|
||||
* @return ERR_OK if the action was taken, any err_t on error
|
||||
*/
|
||||
err_t
|
||||
netconn_join_leave_group(struct netconn *conn,
|
||||
struct ip_addr *multiaddr,
|
||||
struct ip_addr *interface,
|
||||
ip_addr_t *multiaddr,
|
||||
ip_addr_t *netif_addr,
|
||||
enum netconn_igmp join_or_leave)
|
||||
{
|
||||
struct api_msg msg;
|
||||
err_t err;
|
||||
|
||||
LWIP_ERROR("netconn_join_leave_group: invalid conn", (conn != NULL), return ERR_ARG;);
|
||||
|
||||
msg.function = do_join_leave_group;
|
||||
msg.msg.conn = conn;
|
||||
msg.msg.msg.jl.multiaddr = multiaddr;
|
||||
msg.msg.msg.jl.interface = interface;
|
||||
msg.msg.msg.jl.netif_addr = netif_addr;
|
||||
msg.msg.msg.jl.join_or_leave = join_or_leave;
|
||||
TCPIP_APIMSG(&msg);
|
||||
return conn->err;
|
||||
err = TCPIP_APIMSG(&msg);
|
||||
|
||||
NETCONN_SET_SAFE_ERR(conn, err);
|
||||
return err;
|
||||
}
|
||||
#endif /* LWIP_IGMP */
|
||||
|
||||
@@ -521,14 +743,14 @@ netconn_join_leave_group(struct netconn *conn,
|
||||
* Execute a DNS query, only one IP address is returned
|
||||
*
|
||||
* @param name a string representation of the DNS host name to query
|
||||
* @param addr a preallocated struct ip_addr where to store the resolved IP address
|
||||
* @param addr a preallocated ip_addr_t where to store the resolved IP address
|
||||
* @return ERR_OK: resolving succeeded
|
||||
* ERR_MEM: memory error, try again later
|
||||
* ERR_ARG: dns client not initialized or invalid hostname
|
||||
* ERR_VAL: dns server response was invalid
|
||||
*/
|
||||
err_t
|
||||
netconn_gethostbyname(const char *name, struct ip_addr *addr)
|
||||
netconn_gethostbyname(const char *name, ip_addr_t *addr)
|
||||
{
|
||||
struct dns_api_msg msg;
|
||||
err_t err;
|
||||
@@ -537,19 +759,19 @@ netconn_gethostbyname(const char *name, struct ip_addr *addr)
|
||||
LWIP_ERROR("netconn_gethostbyname: invalid name", (name != NULL), return ERR_ARG;);
|
||||
LWIP_ERROR("netconn_gethostbyname: invalid addr", (addr != NULL), return ERR_ARG;);
|
||||
|
||||
sem = sys_sem_new(0);
|
||||
if (sem == SYS_SEM_NULL) {
|
||||
return ERR_MEM;
|
||||
err = sys_sem_new(&sem, 0);
|
||||
if (err != ERR_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
msg.name = name;
|
||||
msg.addr = addr;
|
||||
msg.err = &err;
|
||||
msg.sem = sem;
|
||||
msg.sem = &sem;
|
||||
|
||||
tcpip_callback(do_gethostbyname, &msg);
|
||||
sys_sem_wait(sem);
|
||||
sys_sem_free(sem);
|
||||
sys_sem_wait(&sem);
|
||||
sys_sem_free(&sem);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
1006
src/api/api_msg.c
1006
src/api/api_msg.c
File diff suppressed because it is too large
Load Diff
@@ -44,18 +44,19 @@ static const char *err_strerr[] = {
|
||||
"Ok.", /* ERR_OK 0 */
|
||||
"Out of memory error.", /* ERR_MEM -1 */
|
||||
"Buffer error.", /* ERR_BUF -2 */
|
||||
"Timeout.", /* ERR_TIMEOUT -3 */
|
||||
"Timeout.", /* ERR_TIMEOUT -3 */
|
||||
"Routing problem.", /* ERR_RTE -4 */
|
||||
"Connection aborted.", /* ERR_ABRT -5 */
|
||||
"Connection reset.", /* ERR_RST -6 */
|
||||
"Connection closed.", /* ERR_CLSD -7 */
|
||||
"Not connected.", /* ERR_CONN -8 */
|
||||
"Illegal value.", /* ERR_VAL -9 */
|
||||
"Illegal argument.", /* ERR_ARG -10 */
|
||||
"Address in use.", /* ERR_USE -11 */
|
||||
"Low-level netif error.", /* ERR_IF -12 */
|
||||
"Already connected.", /* ERR_ISCONN -13 */
|
||||
"Operation in progress." /* ERR_INPROGRESS -14 */
|
||||
"Operation in progress.", /* ERR_INPROGRESS -5 */
|
||||
"Illegal value.", /* ERR_VAL -6 */
|
||||
"Operation would block.", /* ERR_WOULDBLOCK -7 */
|
||||
"Address in use.", /* ERR_USE -8 */
|
||||
"Already connected.", /* ERR_ISCONN -9 */
|
||||
"Connection aborted.", /* ERR_ABRT -10 */
|
||||
"Connection reset.", /* ERR_RST -11 */
|
||||
"Connection closed.", /* ERR_CLSD -12 */
|
||||
"Not connected.", /* ERR_CONN -13 */
|
||||
"Illegal argument.", /* ERR_ARG -14 */
|
||||
"Low-level netif error.", /* ERR_IF -15 */
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -57,16 +57,21 @@ netbuf *netbuf_new(void)
|
||||
{
|
||||
struct netbuf *buf;
|
||||
|
||||
buf = memp_malloc(MEMP_NETBUF);
|
||||
buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);
|
||||
if (buf != NULL) {
|
||||
buf->p = NULL;
|
||||
buf->ptr = NULL;
|
||||
buf->addr = NULL;
|
||||
ip_addr_set_any(&buf->addr);
|
||||
buf->port = 0;
|
||||
#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
buf->flags = 0;
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
buf->toport_chksum = 0;
|
||||
#if LWIP_NETBUF_RECVINFO
|
||||
buf->toaddr = NULL;
|
||||
buf->toport = 0;
|
||||
ip_addr_set_any(&buf->toaddr);
|
||||
#endif /* LWIP_NETBUF_RECVINFO */
|
||||
#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */
|
||||
return buf;
|
||||
} else {
|
||||
return NULL;
|
||||
|
||||
@@ -39,16 +39,18 @@
|
||||
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/api.h"
|
||||
#include "lwip/dns.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/** helper struct for gethostbyname_r to access the char* buffer */
|
||||
struct gethostbyname_r_helper {
|
||||
struct ip_addr *addrs;
|
||||
struct ip_addr addr;
|
||||
ip_addr_t *addr_list[2];
|
||||
ip_addr_t addr;
|
||||
char *aliases;
|
||||
};
|
||||
|
||||
@@ -83,13 +85,13 @@ struct hostent*
|
||||
lwip_gethostbyname(const char *name)
|
||||
{
|
||||
err_t err;
|
||||
struct ip_addr addr;
|
||||
ip_addr_t addr;
|
||||
|
||||
/* buffer variables for lwip_gethostbyname() */
|
||||
HOSTENT_STORAGE struct hostent s_hostent;
|
||||
HOSTENT_STORAGE char *s_aliases;
|
||||
HOSTENT_STORAGE struct ip_addr s_hostent_addr;
|
||||
HOSTENT_STORAGE struct ip_addr *s_phostent_addr;
|
||||
HOSTENT_STORAGE ip_addr_t s_hostent_addr;
|
||||
HOSTENT_STORAGE ip_addr_t *s_phostent_addr[2];
|
||||
|
||||
/* query host IP address */
|
||||
err = netconn_gethostbyname(name, &addr);
|
||||
@@ -101,11 +103,12 @@ lwip_gethostbyname(const char *name)
|
||||
|
||||
/* fill hostent */
|
||||
s_hostent_addr = addr;
|
||||
s_phostent_addr = &s_hostent_addr;
|
||||
s_phostent_addr[0] = &s_hostent_addr;
|
||||
s_phostent_addr[1] = NULL;
|
||||
s_hostent.h_name = (char*)name;
|
||||
s_hostent.h_aliases = &s_aliases;
|
||||
s_hostent.h_addrtype = AF_INET;
|
||||
s_hostent.h_length = sizeof(struct ip_addr);
|
||||
s_hostent.h_length = sizeof(ip_addr_t);
|
||||
s_hostent.h_addr_list = (char**)&s_phostent_addr;
|
||||
|
||||
#if DNS_DEBUG
|
||||
@@ -126,7 +129,7 @@ lwip_gethostbyname(const char *name)
|
||||
u8_t idx;
|
||||
for ( idx=0; s_hostent.h_addr_list[idx]; idx++) {
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i] == %p\n", idx, s_hostent.h_addr_list[idx]));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ip_ntoa(s_hostent.h_addr_list[idx])));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("hostent.h_addr_list[%i]-> == %s\n", idx, ip_ntoa((ip_addr_t*)s_hostent.h_addr_list[idx])));
|
||||
}
|
||||
}
|
||||
#endif /* DNS_DEBUG */
|
||||
@@ -177,7 +180,7 @@ lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf,
|
||||
}
|
||||
/* first thing to do: set *result to nothing */
|
||||
*result = NULL;
|
||||
if ((name == NULL) || (ret == NULL) || (buf == 0)) {
|
||||
if ((name == NULL) || (ret == NULL) || (buf == NULL)) {
|
||||
/* not all arguments given */
|
||||
*h_errnop = EINVAL;
|
||||
return -1;
|
||||
@@ -194,10 +197,10 @@ lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf,
|
||||
hostname = ((char*)h) + sizeof(struct gethostbyname_r_helper);
|
||||
|
||||
/* query host IP address */
|
||||
err = netconn_gethostbyname(name, &(h->addr));
|
||||
err = netconn_gethostbyname(name, &h->addr);
|
||||
if (err != ERR_OK) {
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err));
|
||||
*h_errnop = ENSRNOTFOUND;
|
||||
*h_errnop = HOST_NOT_FOUND;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -206,13 +209,14 @@ lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf,
|
||||
hostname[namelen] = 0;
|
||||
|
||||
/* fill hostent */
|
||||
h->addrs = &(h->addr);
|
||||
h->addr_list[0] = &h->addr;
|
||||
h->addr_list[1] = NULL;
|
||||
h->aliases = NULL;
|
||||
ret->h_name = (char*)hostname;
|
||||
ret->h_aliases = &(h->aliases);
|
||||
ret->h_name = hostname;
|
||||
ret->h_aliases = &h->aliases;
|
||||
ret->h_addrtype = AF_INET;
|
||||
ret->h_length = sizeof(struct ip_addr);
|
||||
ret->h_addr_list = (char**)&(h->addrs);
|
||||
ret->h_length = sizeof(ip_addr_t);
|
||||
ret->h_addr_list = (char**)&h->addr_list;
|
||||
|
||||
/* set result != NULL */
|
||||
*result = ret;
|
||||
@@ -235,7 +239,7 @@ lwip_freeaddrinfo(struct addrinfo *ai)
|
||||
|
||||
while (ai != NULL) {
|
||||
next = ai->ai_next;
|
||||
mem_free(ai);
|
||||
memp_free(MEMP_NETDB, ai);
|
||||
ai = next;
|
||||
}
|
||||
}
|
||||
@@ -264,7 +268,7 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
|
||||
const struct addrinfo *hints, struct addrinfo **res)
|
||||
{
|
||||
err_t err;
|
||||
struct ip_addr addr;
|
||||
ip_addr_t addr;
|
||||
struct addrinfo *ai;
|
||||
struct sockaddr_in *sa = NULL;
|
||||
int port_nr = 0;
|
||||
@@ -296,7 +300,7 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
|
||||
}
|
||||
} else {
|
||||
/* service location specified, use loopback address */
|
||||
addr.addr = htonl(INADDR_LOOPBACK);
|
||||
ip_addr_set_loopback(&addr);
|
||||
}
|
||||
|
||||
total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_in);
|
||||
@@ -305,17 +309,20 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
|
||||
LWIP_ASSERT("namelen is too long", (namelen + 1) <= (mem_size_t)-1);
|
||||
total_size += namelen + 1;
|
||||
}
|
||||
ai = mem_malloc(total_size);
|
||||
/* If this fails, please report to lwip-devel! :-) */
|
||||
LWIP_ASSERT("total_size <= NETDB_ELEM_SIZE: please report this!",
|
||||
total_size <= NETDB_ELEM_SIZE);
|
||||
ai = (struct addrinfo *)memp_malloc(MEMP_NETDB);
|
||||
if (ai == NULL) {
|
||||
goto memerr;
|
||||
}
|
||||
memset(ai, 0, total_size);
|
||||
sa = (struct sockaddr_in*)((u8_t*)ai + sizeof(struct addrinfo));
|
||||
/* set up sockaddr */
|
||||
sa->sin_addr.s_addr = addr.addr;
|
||||
inet_addr_from_ipaddr(&sa->sin_addr, &addr);
|
||||
sa->sin_family = AF_INET;
|
||||
sa->sin_len = sizeof(struct sockaddr_in);
|
||||
sa->sin_port = htons(port_nr);
|
||||
sa->sin_port = htons((u16_t)port_nr);
|
||||
|
||||
/* set up addrinfo */
|
||||
ai->ai_family = AF_INET;
|
||||
@@ -338,7 +345,7 @@ lwip_getaddrinfo(const char *nodename, const char *servname,
|
||||
return 0;
|
||||
memerr:
|
||||
if (ai != NULL) {
|
||||
mem_free(ai);
|
||||
memp_free(MEMP_NETDB, ai);
|
||||
}
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
* Call netif_add() inside the tcpip_thread context.
|
||||
*/
|
||||
void
|
||||
do_netifapi_netif_add( struct netifapi_msg_msg *msg)
|
||||
do_netifapi_netif_add(struct netifapi_msg_msg *msg)
|
||||
{
|
||||
if (!netif_add( msg->netif,
|
||||
msg->msg.add.ipaddr,
|
||||
@@ -62,7 +62,7 @@ do_netifapi_netif_add( struct netifapi_msg_msg *msg)
|
||||
* Call netif_set_addr() inside the tcpip_thread context.
|
||||
*/
|
||||
void
|
||||
do_netifapi_netif_set_addr( struct netifapi_msg_msg *msg)
|
||||
do_netifapi_netif_set_addr(struct netifapi_msg_msg *msg)
|
||||
{
|
||||
netif_set_addr( msg->netif,
|
||||
msg->msg.add.ipaddr,
|
||||
@@ -77,11 +77,10 @@ do_netifapi_netif_set_addr( struct netifapi_msg_msg *msg)
|
||||
* tcpip_thread context.
|
||||
*/
|
||||
void
|
||||
do_netifapi_netif_common( struct netifapi_msg_msg *msg)
|
||||
do_netifapi_netif_common(struct netifapi_msg_msg *msg)
|
||||
{
|
||||
if (msg->msg.common.errtfunc!=NULL) {
|
||||
msg->err =
|
||||
msg->msg.common.errtfunc(msg->netif);
|
||||
if (msg->msg.common.errtfunc != NULL) {
|
||||
msg->err = msg->msg.common.errtfunc(msg->netif);
|
||||
} else {
|
||||
msg->err = ERR_OK;
|
||||
msg->msg.common.voidfunc(msg->netif);
|
||||
@@ -97,12 +96,12 @@ do_netifapi_netif_common( struct netifapi_msg_msg *msg)
|
||||
*/
|
||||
err_t
|
||||
netifapi_netif_add(struct netif *netif,
|
||||
struct ip_addr *ipaddr,
|
||||
struct ip_addr *netmask,
|
||||
struct ip_addr *gw,
|
||||
ip_addr_t *ipaddr,
|
||||
ip_addr_t *netmask,
|
||||
ip_addr_t *gw,
|
||||
void *state,
|
||||
err_t (* init)(struct netif *netif),
|
||||
err_t (* input)(struct pbuf *p, struct netif *netif))
|
||||
netif_init_fn init,
|
||||
netif_input_fn input)
|
||||
{
|
||||
struct netifapi_msg msg;
|
||||
msg.function = do_netifapi_netif_add;
|
||||
@@ -125,9 +124,9 @@ netifapi_netif_add(struct netif *netif,
|
||||
*/
|
||||
err_t
|
||||
netifapi_netif_set_addr(struct netif *netif,
|
||||
struct ip_addr *ipaddr,
|
||||
struct ip_addr *netmask,
|
||||
struct ip_addr *gw)
|
||||
ip_addr_t *ipaddr,
|
||||
ip_addr_t *netmask,
|
||||
ip_addr_t *gw)
|
||||
{
|
||||
struct netifapi_msg msg;
|
||||
msg.function = do_netifapi_netif_set_addr;
|
||||
@@ -146,9 +145,8 @@ netifapi_netif_set_addr(struct netif *netif,
|
||||
* @note use only for functions where there is only "netif" parameter.
|
||||
*/
|
||||
err_t
|
||||
netifapi_netif_common( struct netif *netif,
|
||||
void (* voidfunc)(struct netif *netif),
|
||||
err_t (* errtfunc)(struct netif *netif) )
|
||||
netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc,
|
||||
netifapi_errt_fn errtfunc)
|
||||
{
|
||||
struct netifapi_msg msg;
|
||||
msg.function = do_netifapi_netif_common;
|
||||
|
||||
1185
src/api/sockets.c
1185
src/api/sockets.c
File diff suppressed because it is too large
Load Diff
397
src/api/tcpip.c
397
src/api/tcpip.c
@@ -42,182 +42,23 @@
|
||||
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip_frag.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/autoip.h"
|
||||
#include "lwip/dhcp.h"
|
||||
#include "lwip/igmp.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/tcpip.h"
|
||||
#include "lwip/init.h"
|
||||
#include "netif/etharp.h"
|
||||
#include "netif/ppp_oe.h"
|
||||
|
||||
/* global variables */
|
||||
static void (* tcpip_init_done)(void *arg);
|
||||
static tcpip_init_done_fn tcpip_init_done;
|
||||
static void *tcpip_init_done_arg;
|
||||
static sys_mbox_t mbox = SYS_MBOX_NULL;
|
||||
static sys_mbox_t mbox;
|
||||
|
||||
#if LWIP_TCPIP_CORE_LOCKING
|
||||
/** The global semaphore to lock the stack. */
|
||||
sys_sem_t lock_tcpip_core;
|
||||
sys_mutex_t lock_tcpip_core;
|
||||
#endif /* LWIP_TCPIP_CORE_LOCKING */
|
||||
|
||||
#if LWIP_TCP
|
||||
/* global variable that shows if the tcp timer is currently scheduled or not */
|
||||
static int tcpip_tcp_timer_active;
|
||||
|
||||
/**
|
||||
* Timer callback function that calls tcp_tmr() and reschedules itself.
|
||||
*
|
||||
* @param arg unused argument
|
||||
*/
|
||||
static void
|
||||
tcpip_tcp_timer(void *arg)
|
||||
{
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
|
||||
/* call TCP timer handler */
|
||||
tcp_tmr();
|
||||
/* timer still needed? */
|
||||
if (tcp_active_pcbs || tcp_tw_pcbs) {
|
||||
/* restart timer */
|
||||
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
|
||||
} else {
|
||||
/* disable timer */
|
||||
tcpip_tcp_timer_active = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if !NO_SYS
|
||||
/**
|
||||
* Called from TCP_REG when registering a new PCB:
|
||||
* the reason is to have the TCP timer only running when
|
||||
* there are active (or time-wait) PCBs.
|
||||
*/
|
||||
void
|
||||
tcp_timer_needed(void)
|
||||
{
|
||||
/* timer is off but needed again? */
|
||||
if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
|
||||
/* enable and start timer */
|
||||
tcpip_tcp_timer_active = 1;
|
||||
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
|
||||
}
|
||||
}
|
||||
#endif /* !NO_SYS */
|
||||
#endif /* LWIP_TCP */
|
||||
|
||||
#if IP_REASSEMBLY
|
||||
/**
|
||||
* Timer callback function that calls ip_reass_tmr() and reschedules itself.
|
||||
*
|
||||
* @param arg unused argument
|
||||
*/
|
||||
static void
|
||||
ip_reass_timer(void *arg)
|
||||
{
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: ip_reass_tmr()\n"));
|
||||
ip_reass_tmr();
|
||||
sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL);
|
||||
}
|
||||
#endif /* IP_REASSEMBLY */
|
||||
|
||||
#if LWIP_ARP
|
||||
/**
|
||||
* Timer callback function that calls etharp_tmr() and reschedules itself.
|
||||
*
|
||||
* @param arg unused argument
|
||||
*/
|
||||
static void
|
||||
arp_timer(void *arg)
|
||||
{
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: etharp_tmr()\n"));
|
||||
etharp_tmr();
|
||||
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
|
||||
}
|
||||
#endif /* LWIP_ARP */
|
||||
|
||||
#if LWIP_DHCP
|
||||
/**
|
||||
* Timer callback function that calls dhcp_coarse_tmr() and reschedules itself.
|
||||
*
|
||||
* @param arg unused argument
|
||||
*/
|
||||
static void
|
||||
dhcp_timer_coarse(void *arg)
|
||||
{
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: dhcp_coarse_tmr()\n"));
|
||||
dhcp_coarse_tmr();
|
||||
sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Timer callback function that calls dhcp_fine_tmr() and reschedules itself.
|
||||
*
|
||||
* @param arg unused argument
|
||||
*/
|
||||
static void
|
||||
dhcp_timer_fine(void *arg)
|
||||
{
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: dhcp_fine_tmr()\n"));
|
||||
dhcp_fine_tmr();
|
||||
sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
|
||||
}
|
||||
#endif /* LWIP_DHCP */
|
||||
|
||||
#if LWIP_AUTOIP
|
||||
/**
|
||||
* Timer callback function that calls autoip_tmr() and reschedules itself.
|
||||
*
|
||||
* @param arg unused argument
|
||||
*/
|
||||
static void
|
||||
autoip_timer(void *arg)
|
||||
{
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: autoip_tmr()\n"));
|
||||
autoip_tmr();
|
||||
sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL);
|
||||
}
|
||||
#endif /* LWIP_AUTOIP */
|
||||
|
||||
#if LWIP_IGMP
|
||||
/**
|
||||
* Timer callback function that calls igmp_tmr() and reschedules itself.
|
||||
*
|
||||
* @param arg unused argument
|
||||
*/
|
||||
static void
|
||||
igmp_timer(void *arg)
|
||||
{
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: igmp_tmr()\n"));
|
||||
igmp_tmr();
|
||||
sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL);
|
||||
}
|
||||
#endif /* LWIP_IGMP */
|
||||
|
||||
#if LWIP_DNS
|
||||
/**
|
||||
* Timer callback function that calls dns_tmr() and reschedules itself.
|
||||
*
|
||||
* @param arg unused argument
|
||||
*/
|
||||
static void
|
||||
dns_timer(void *arg)
|
||||
{
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: dns_tmr()\n"));
|
||||
dns_tmr();
|
||||
sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL);
|
||||
}
|
||||
#endif /* LWIP_DNS */
|
||||
|
||||
/**
|
||||
* The main lwIP thread. This thread has exclusive access to lwIP core functions
|
||||
@@ -235,33 +76,17 @@ tcpip_thread(void *arg)
|
||||
struct tcpip_msg *msg;
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
|
||||
#if IP_REASSEMBLY
|
||||
sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL);
|
||||
#endif /* IP_REASSEMBLY */
|
||||
#if LWIP_ARP
|
||||
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
|
||||
#endif /* LWIP_ARP */
|
||||
#if LWIP_DHCP
|
||||
sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL);
|
||||
sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
|
||||
#endif /* LWIP_DHCP */
|
||||
#if LWIP_AUTOIP
|
||||
sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL);
|
||||
#endif /* LWIP_AUTOIP */
|
||||
#if LWIP_IGMP
|
||||
sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL);
|
||||
#endif /* LWIP_IGMP */
|
||||
#if LWIP_DNS
|
||||
sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL);
|
||||
#endif /* LWIP_DNS */
|
||||
|
||||
if (tcpip_init_done != NULL) {
|
||||
tcpip_init_done(tcpip_init_done_arg);
|
||||
}
|
||||
|
||||
LOCK_TCPIP_CORE();
|
||||
while (1) { /* MAIN Loop */
|
||||
sys_mbox_fetch(mbox, (void *)&msg);
|
||||
UNLOCK_TCPIP_CORE();
|
||||
LWIP_TCPIP_THREAD_ALIVE();
|
||||
/* wait for a message, timeouts are processed while waiting */
|
||||
sys_timeouts_mbox_fetch(&mbox, (void **)&msg);
|
||||
LOCK_TCPIP_CORE();
|
||||
switch (msg->type) {
|
||||
#if LWIP_NETCONN
|
||||
case TCPIP_MSG_API:
|
||||
@@ -270,17 +95,20 @@ tcpip_thread(void *arg)
|
||||
break;
|
||||
#endif /* LWIP_NETCONN */
|
||||
|
||||
#if !LWIP_TCPIP_CORE_LOCKING_INPUT
|
||||
case TCPIP_MSG_INPKT:
|
||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg));
|
||||
#if LWIP_ARP
|
||||
if (msg->msg.inp.netif->flags & NETIF_FLAG_ETHARP) {
|
||||
#if LWIP_ETHERNET
|
||||
if (msg->msg.inp.netif->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) {
|
||||
ethernet_input(msg->msg.inp.p, msg->msg.inp.netif);
|
||||
} else
|
||||
#endif /* LWIP_ARP */
|
||||
{ ip_input(msg->msg.inp.p, msg->msg.inp.netif);
|
||||
#endif /* LWIP_ETHERNET */
|
||||
{
|
||||
ip_input(msg->msg.inp.p, msg->msg.inp.netif);
|
||||
}
|
||||
memp_free(MEMP_TCPIP_MSG_INPKT, msg);
|
||||
break;
|
||||
#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */
|
||||
|
||||
#if LWIP_NETIF_API
|
||||
case TCPIP_MSG_NETIFAPI:
|
||||
@@ -289,12 +117,7 @@ tcpip_thread(void *arg)
|
||||
break;
|
||||
#endif /* LWIP_NETIF_API */
|
||||
|
||||
case TCPIP_MSG_CALLBACK:
|
||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
|
||||
msg->msg.cb.f(msg->msg.cb.ctx);
|
||||
memp_free(MEMP_TCPIP_MSG_API, msg);
|
||||
break;
|
||||
|
||||
#if LWIP_TCPIP_TIMEOUT
|
||||
case TCPIP_MSG_TIMEOUT:
|
||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg));
|
||||
sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg);
|
||||
@@ -305,8 +128,22 @@ tcpip_thread(void *arg)
|
||||
sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg);
|
||||
memp_free(MEMP_TCPIP_MSG_API, msg);
|
||||
break;
|
||||
#endif /* LWIP_TCPIP_TIMEOUT */
|
||||
|
||||
case TCPIP_MSG_CALLBACK:
|
||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
|
||||
msg->msg.cb.function(msg->msg.cb.ctx);
|
||||
memp_free(MEMP_TCPIP_MSG_API, msg);
|
||||
break;
|
||||
|
||||
case TCPIP_MSG_CALLBACK_STATIC:
|
||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK_STATIC %p\n", (void *)msg));
|
||||
msg->msg.cb.function(msg->msg.cb.ctx);
|
||||
break;
|
||||
|
||||
default:
|
||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type));
|
||||
LWIP_ASSERT("tcpip_thread: invalid message", 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -316,30 +153,47 @@ tcpip_thread(void *arg)
|
||||
* Pass a received packet to tcpip_thread for input processing
|
||||
*
|
||||
* @param p the received packet, p->payload pointing to the Ethernet header or
|
||||
* to an IP header (if netif doesn't got NETIF_FLAG_ETHARP flag)
|
||||
* to an IP header (if inp doesn't have NETIF_FLAG_ETHARP or
|
||||
* NETIF_FLAG_ETHERNET flags)
|
||||
* @param inp the network interface on which the packet was received
|
||||
*/
|
||||
err_t
|
||||
tcpip_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
#if LWIP_TCPIP_CORE_LOCKING_INPUT
|
||||
err_t ret;
|
||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_input: PACKET %p/%p\n", (void *)p, (void *)inp));
|
||||
LOCK_TCPIP_CORE();
|
||||
#if LWIP_ETHERNET
|
||||
if (inp->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) {
|
||||
ret = ethernet_input(p, inp);
|
||||
} else
|
||||
#endif /* LWIP_ETHERNET */
|
||||
{
|
||||
ret = ip_input(p, inp);
|
||||
}
|
||||
UNLOCK_TCPIP_CORE();
|
||||
return ret;
|
||||
#else /* LWIP_TCPIP_CORE_LOCKING_INPUT */
|
||||
struct tcpip_msg *msg;
|
||||
|
||||
if (mbox != SYS_MBOX_NULL) {
|
||||
msg = memp_malloc(MEMP_TCPIP_MSG_INPKT);
|
||||
if (msg == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
msg->type = TCPIP_MSG_INPKT;
|
||||
msg->msg.inp.p = p;
|
||||
msg->msg.inp.netif = inp;
|
||||
if (sys_mbox_trypost(mbox, msg) != ERR_OK) {
|
||||
memp_free(MEMP_TCPIP_MSG_INPKT, msg);
|
||||
return ERR_MEM;
|
||||
}
|
||||
return ERR_OK;
|
||||
if (!sys_mbox_valid(&mbox)) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
return ERR_VAL;
|
||||
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT);
|
||||
if (msg == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
msg->type = TCPIP_MSG_INPKT;
|
||||
msg->msg.inp.p = p;
|
||||
msg->msg.inp.netif = inp;
|
||||
if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
|
||||
memp_free(MEMP_TCPIP_MSG_INPKT, msg);
|
||||
return ERR_MEM;
|
||||
}
|
||||
return ERR_OK;
|
||||
#endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -354,23 +208,23 @@ tcpip_input(struct pbuf *p, struct netif *inp)
|
||||
* @return ERR_OK if the function was called, another err_t if not
|
||||
*/
|
||||
err_t
|
||||
tcpip_callback_with_block(void (*f)(void *ctx), void *ctx, u8_t block)
|
||||
tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block)
|
||||
{
|
||||
struct tcpip_msg *msg;
|
||||
|
||||
if (mbox != SYS_MBOX_NULL) {
|
||||
msg = memp_malloc(MEMP_TCPIP_MSG_API);
|
||||
if (sys_mbox_valid(&mbox)) {
|
||||
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
|
||||
if (msg == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
msg->type = TCPIP_MSG_CALLBACK;
|
||||
msg->msg.cb.f = f;
|
||||
msg->msg.cb.function = function;
|
||||
msg->msg.cb.ctx = ctx;
|
||||
if (block) {
|
||||
sys_mbox_post(mbox, msg);
|
||||
sys_mbox_post(&mbox, msg);
|
||||
} else {
|
||||
if (sys_mbox_trypost(mbox, msg) != ERR_OK) {
|
||||
if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
|
||||
memp_free(MEMP_TCPIP_MSG_API, msg);
|
||||
return ERR_MEM;
|
||||
}
|
||||
@@ -380,10 +234,11 @@ tcpip_callback_with_block(void (*f)(void *ctx), void *ctx, u8_t block)
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
#if LWIP_TCPIP_TIMEOUT
|
||||
/**
|
||||
* call sys_timeout in tcpip_thread
|
||||
*
|
||||
* @param msec time in miliseconds for timeout
|
||||
* @param msec time in milliseconds for timeout
|
||||
* @param h function to be called on timeout
|
||||
* @param arg argument to pass to timeout function h
|
||||
* @return ERR_MEM on memory error, ERR_OK otherwise
|
||||
@@ -393,8 +248,8 @@ tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
|
||||
{
|
||||
struct tcpip_msg *msg;
|
||||
|
||||
if (mbox != SYS_MBOX_NULL) {
|
||||
msg = memp_malloc(MEMP_TCPIP_MSG_API);
|
||||
if (sys_mbox_valid(&mbox)) {
|
||||
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
|
||||
if (msg == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
@@ -403,7 +258,7 @@ tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
|
||||
msg->msg.tmo.msecs = msecs;
|
||||
msg->msg.tmo.h = h;
|
||||
msg->msg.tmo.arg = arg;
|
||||
sys_mbox_post(mbox, msg);
|
||||
sys_mbox_post(&mbox, msg);
|
||||
return ERR_OK;
|
||||
}
|
||||
return ERR_VAL;
|
||||
@@ -412,7 +267,7 @@ tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
|
||||
/**
|
||||
* call sys_untimeout in tcpip_thread
|
||||
*
|
||||
* @param msec time in miliseconds for timeout
|
||||
* @param msec time in milliseconds for timeout
|
||||
* @param h function to be called on timeout
|
||||
* @param arg argument to pass to timeout function h
|
||||
* @return ERR_MEM on memory error, ERR_OK otherwise
|
||||
@@ -422,8 +277,8 @@ tcpip_untimeout(sys_timeout_handler h, void *arg)
|
||||
{
|
||||
struct tcpip_msg *msg;
|
||||
|
||||
if (mbox != SYS_MBOX_NULL) {
|
||||
msg = memp_malloc(MEMP_TCPIP_MSG_API);
|
||||
if (sys_mbox_valid(&mbox)) {
|
||||
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
|
||||
if (msg == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
@@ -431,11 +286,12 @@ tcpip_untimeout(sys_timeout_handler h, void *arg)
|
||||
msg->type = TCPIP_MSG_UNTIMEOUT;
|
||||
msg->msg.tmo.h = h;
|
||||
msg->msg.tmo.arg = arg;
|
||||
sys_mbox_post(mbox, msg);
|
||||
sys_mbox_post(&mbox, msg);
|
||||
return ERR_OK;
|
||||
}
|
||||
return ERR_VAL;
|
||||
}
|
||||
#endif /* LWIP_TCPIP_TIMEOUT */
|
||||
|
||||
#if LWIP_NETCONN
|
||||
/**
|
||||
@@ -450,13 +306,17 @@ err_t
|
||||
tcpip_apimsg(struct api_msg *apimsg)
|
||||
{
|
||||
struct tcpip_msg msg;
|
||||
#ifdef LWIP_DEBUG
|
||||
/* catch functions that don't set err */
|
||||
apimsg->msg.err = ERR_VAL;
|
||||
#endif
|
||||
|
||||
if (mbox != SYS_MBOX_NULL) {
|
||||
if (sys_mbox_valid(&mbox)) {
|
||||
msg.type = TCPIP_MSG_API;
|
||||
msg.msg.apimsg = apimsg;
|
||||
sys_mbox_post(mbox, &msg);
|
||||
sys_arch_sem_wait(apimsg->msg.conn->op_completed, 0);
|
||||
return ERR_OK;
|
||||
sys_mbox_post(&mbox, &msg);
|
||||
sys_arch_sem_wait(&apimsg->msg.conn->op_completed, 0);
|
||||
return apimsg->msg.err;
|
||||
}
|
||||
return ERR_VAL;
|
||||
}
|
||||
@@ -473,10 +333,15 @@ tcpip_apimsg(struct api_msg *apimsg)
|
||||
err_t
|
||||
tcpip_apimsg_lock(struct api_msg *apimsg)
|
||||
{
|
||||
#ifdef LWIP_DEBUG
|
||||
/* catch functions that don't set err */
|
||||
apimsg->msg.err = ERR_VAL;
|
||||
#endif
|
||||
|
||||
LOCK_TCPIP_CORE();
|
||||
apimsg->function(&(apimsg->msg));
|
||||
UNLOCK_TCPIP_CORE();
|
||||
return ERR_OK;
|
||||
return apimsg->msg.err;
|
||||
|
||||
}
|
||||
#endif /* LWIP_TCPIP_CORE_LOCKING */
|
||||
@@ -496,18 +361,18 @@ tcpip_netifapi(struct netifapi_msg* netifapimsg)
|
||||
{
|
||||
struct tcpip_msg msg;
|
||||
|
||||
if (mbox != SYS_MBOX_NULL) {
|
||||
netifapimsg->msg.sem = sys_sem_new(0);
|
||||
if (netifapimsg->msg.sem == SYS_SEM_NULL) {
|
||||
netifapimsg->msg.err = ERR_MEM;
|
||||
return netifapimsg->msg.err;
|
||||
if (sys_mbox_valid(&mbox)) {
|
||||
err_t err = sys_sem_new(&netifapimsg->msg.sem, 0);
|
||||
if (err != ERR_OK) {
|
||||
netifapimsg->msg.err = err;
|
||||
return err;
|
||||
}
|
||||
|
||||
msg.type = TCPIP_MSG_NETIFAPI;
|
||||
msg.msg.netifapimsg = netifapimsg;
|
||||
sys_mbox_post(mbox, &msg);
|
||||
sys_sem_wait(netifapimsg->msg.sem);
|
||||
sys_sem_free(netifapimsg->msg.sem);
|
||||
sys_mbox_post(&mbox, &msg);
|
||||
sys_sem_wait(&netifapimsg->msg.sem);
|
||||
sys_sem_free(&netifapimsg->msg.sem);
|
||||
return netifapimsg->msg.err;
|
||||
}
|
||||
return ERR_VAL;
|
||||
@@ -532,6 +397,52 @@ tcpip_netifapi_lock(struct netifapi_msg* netifapimsg)
|
||||
#endif /* !LWIP_TCPIP_CORE_LOCKING */
|
||||
#endif /* LWIP_NETIF_API */
|
||||
|
||||
/**
|
||||
* Allocate a structure for a static callback message and initialize it.
|
||||
* This is intended to be used to send "static" messages from interrupt context.
|
||||
*
|
||||
* @param function the function to call
|
||||
* @param ctx parameter passed to function
|
||||
* @return a struct pointer to pass to tcpip_trycallback().
|
||||
*/
|
||||
struct tcpip_callback_msg* tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx)
|
||||
{
|
||||
struct tcpip_msg *msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
|
||||
if (msg == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
msg->type = TCPIP_MSG_CALLBACK_STATIC;
|
||||
msg->msg.cb.function = function;
|
||||
msg->msg.cb.ctx = ctx;
|
||||
return (struct tcpip_callback_msg*)msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free a callback message allocated by tcpip_callbackmsg_new().
|
||||
*
|
||||
* @param msg the message to free
|
||||
*/
|
||||
void tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg)
|
||||
{
|
||||
memp_free(MEMP_TCPIP_MSG_API, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to post a callback-message to the tcpip_thread mbox
|
||||
* This is intended to be used to send "static" messages from interrupt context.
|
||||
*
|
||||
* @param msg pointer to the message to post
|
||||
* @return sys_mbox_trypost() return code
|
||||
*/
|
||||
err_t
|
||||
tcpip_trycallback(struct tcpip_callback_msg* msg)
|
||||
{
|
||||
if (!sys_mbox_valid(&mbox)) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
return sys_mbox_trypost(&mbox, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize this module:
|
||||
* - initialize all sub modules
|
||||
@@ -541,15 +452,19 @@ tcpip_netifapi_lock(struct netifapi_msg* netifapimsg)
|
||||
* @param arg argument to pass to initfunc
|
||||
*/
|
||||
void
|
||||
tcpip_init(void (* initfunc)(void *), void *arg)
|
||||
tcpip_init(tcpip_init_done_fn initfunc, void *arg)
|
||||
{
|
||||
lwip_init();
|
||||
|
||||
tcpip_init_done = initfunc;
|
||||
tcpip_init_done_arg = arg;
|
||||
mbox = sys_mbox_new(TCPIP_MBOX_SIZE);
|
||||
if(sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK) {
|
||||
LWIP_ASSERT("failed to create tcpip_thread mbox", 0);
|
||||
}
|
||||
#if LWIP_TCPIP_CORE_LOCKING
|
||||
lock_tcpip_core = sys_sem_new(1);
|
||||
if(sys_mutex_new(&lock_tcpip_core) != ERR_OK) {
|
||||
LWIP_ASSERT("failed to create lock_tcpip_core", 0);
|
||||
}
|
||||
#endif /* LWIP_TCPIP_CORE_LOCKING */
|
||||
|
||||
sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
|
||||
@@ -564,7 +479,7 @@ tcpip_init(void (* initfunc)(void *), void *arg)
|
||||
static void
|
||||
pbuf_free_int(void *p)
|
||||
{
|
||||
struct pbuf *q = p;
|
||||
struct pbuf *q = (struct pbuf *)p;
|
||||
pbuf_free(q);
|
||||
}
|
||||
|
||||
|
||||
108
src/core/def.c
Normal file
108
src/core/def.c
Normal file
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* @file
|
||||
* Common functions used throughout the stack.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Simon Goldschmidt
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/def.h"
|
||||
|
||||
/**
|
||||
* These are reference implementations of the byte swapping functions.
|
||||
* Again with the aim of being simple, correct and fully portable.
|
||||
* Byte swapping is the second thing you would want to optimize. You will
|
||||
* need to port it to your architecture and in your cc.h:
|
||||
*
|
||||
* #define LWIP_PLATFORM_BYTESWAP 1
|
||||
* #define LWIP_PLATFORM_HTONS(x) <your_htons>
|
||||
* #define LWIP_PLATFORM_HTONL(x) <your_htonl>
|
||||
*
|
||||
* Note ntohs() and ntohl() are merely references to the htonx counterparts.
|
||||
*/
|
||||
|
||||
#if (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
|
||||
/**
|
||||
* Convert an u16_t from host- to network byte order.
|
||||
*
|
||||
* @param n u16_t in host byte order
|
||||
* @return n in network byte order
|
||||
*/
|
||||
u16_t
|
||||
lwip_htons(u16_t n)
|
||||
{
|
||||
return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an u16_t from network- to host byte order.
|
||||
*
|
||||
* @param n u16_t in network byte order
|
||||
* @return n in host byte order
|
||||
*/
|
||||
u16_t
|
||||
lwip_ntohs(u16_t n)
|
||||
{
|
||||
return lwip_htons(n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an u32_t from host- to network byte order.
|
||||
*
|
||||
* @param n u32_t in host byte order
|
||||
* @return n in network byte order
|
||||
*/
|
||||
u32_t
|
||||
lwip_htonl(u32_t n)
|
||||
{
|
||||
return ((n & 0xff) << 24) |
|
||||
((n & 0xff00) << 8) |
|
||||
((n & 0xff0000UL) >> 8) |
|
||||
((n & 0xff000000UL) >> 24);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an u32_t from network- to host byte order.
|
||||
*
|
||||
* @param n u32_t in network byte order
|
||||
* @return n in host byte order
|
||||
*/
|
||||
u32_t
|
||||
lwip_ntohl(u32_t n)
|
||||
{
|
||||
return lwip_htonl(n);
|
||||
}
|
||||
|
||||
#endif /* (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) */
|
||||
1010
src/core/dhcp.c
1010
src/core/dhcp.c
File diff suppressed because it is too large
Load Diff
228
src/core/dns.c
228
src/core/dns.c
@@ -78,13 +78,14 @@
|
||||
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/dns.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/** DNS server IP address */
|
||||
#ifndef DNS_SERVER_ADDRESS
|
||||
#define DNS_SERVER_ADDRESS inet_addr("208.67.222.222") /* resolver1.opendns.com */
|
||||
#define DNS_SERVER_ADDRESS(ipaddr) (ip4_addr_set_u32(ipaddr, ipaddr_addr("208.67.222.222"))) /* resolver1.opendns.com */
|
||||
#endif
|
||||
|
||||
/** DNS server port address */
|
||||
@@ -141,40 +142,26 @@ PACK_STRUCT_END
|
||||
#endif
|
||||
#define SIZEOF_DNS_HDR 12
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
/** DNS query message structure */
|
||||
/** DNS query message structure.
|
||||
No packing needed: only used locally on the stack. */
|
||||
struct dns_query {
|
||||
/* DNS query record starts with either a domain name or a pointer
|
||||
to a name already present somewhere in the packet. */
|
||||
PACK_STRUCT_FIELD(u16_t type);
|
||||
PACK_STRUCT_FIELD(u16_t class);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
u16_t type;
|
||||
u16_t cls;
|
||||
};
|
||||
#define SIZEOF_DNS_QUERY 4
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
/** DNS answer message structure */
|
||||
/** DNS answer message structure.
|
||||
No packing needed: only used locally on the stack. */
|
||||
struct dns_answer {
|
||||
/* DNS answer record starts with either a domain name or a pointer
|
||||
to a name already present somewhere in the packet. */
|
||||
PACK_STRUCT_FIELD(u16_t type);
|
||||
PACK_STRUCT_FIELD(u16_t class);
|
||||
PACK_STRUCT_FIELD(u32_t ttl);
|
||||
PACK_STRUCT_FIELD(u16_t len);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
u16_t type;
|
||||
u16_t cls;
|
||||
u32_t ttl;
|
||||
u16_t len;
|
||||
};
|
||||
#define SIZEOF_DNS_ANSWER 10
|
||||
|
||||
/** DNS table entry */
|
||||
@@ -187,21 +174,13 @@ struct dns_table_entry {
|
||||
u8_t err;
|
||||
u32_t ttl;
|
||||
char name[DNS_MAX_NAME_LENGTH];
|
||||
struct ip_addr ipaddr;
|
||||
ip_addr_t ipaddr;
|
||||
/* pointer to callback on DNS query done */
|
||||
dns_found_callback found;
|
||||
void *arg;
|
||||
};
|
||||
|
||||
#if DNS_LOCAL_HOSTLIST
|
||||
/** struct used for local host-list */
|
||||
struct local_hostlist_entry {
|
||||
/** static hostname */
|
||||
const char *name;
|
||||
/** static host address in network byteorder */
|
||||
u32_t addr;
|
||||
struct local_hostlist_entry *next;
|
||||
};
|
||||
|
||||
#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
|
||||
/** Local host-list. For hostnames in this list, no
|
||||
@@ -229,7 +208,7 @@ static void dns_init_local();
|
||||
|
||||
|
||||
/* forward declarations */
|
||||
static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);
|
||||
static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port);
|
||||
static void dns_check_entries(void);
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
@@ -240,11 +219,10 @@ static void dns_check_entries(void);
|
||||
static struct udp_pcb *dns_pcb;
|
||||
static u8_t dns_seqno;
|
||||
static struct dns_table_entry dns_table[DNS_TABLE_SIZE];
|
||||
static struct ip_addr dns_servers[DNS_MAX_SERVERS];
|
||||
|
||||
#if (DNS_USES_STATIC_BUF == 1)
|
||||
static u8_t dns_payload[DNS_MSG_SIZE];
|
||||
#endif /* (DNS_USES_STATIC_BUF == 1) */
|
||||
static ip_addr_t dns_servers[DNS_MAX_SERVERS];
|
||||
/** Contiguous buffer for processing responses */
|
||||
static u8_t dns_payload_buffer[LWIP_MEM_ALIGN_BUFFER(DNS_MSG_SIZE)];
|
||||
static u8_t* dns_payload;
|
||||
|
||||
/**
|
||||
* Initialize the resolver: set up the UDP pcb and configure the default server
|
||||
@@ -253,10 +231,12 @@ static u8_t dns_payload[DNS_MSG_SIZE];
|
||||
void
|
||||
dns_init()
|
||||
{
|
||||
struct ip_addr dnsserver;
|
||||
ip_addr_t dnsserver;
|
||||
|
||||
dns_payload = (u8_t *)LWIP_MEM_ALIGN(dns_payload_buffer);
|
||||
|
||||
/* initialize default DNS server address */
|
||||
dnsserver.addr = DNS_SERVER_ADDRESS;
|
||||
DNS_SERVER_ADDRESS(&dnsserver);
|
||||
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("dns_init: initializing\n"));
|
||||
|
||||
@@ -290,10 +270,10 @@ dns_init()
|
||||
* @param dnsserver IP address of the DNS server to set
|
||||
*/
|
||||
void
|
||||
dns_setserver(u8_t numdns, struct ip_addr *dnsserver)
|
||||
dns_setserver(u8_t numdns, ip_addr_t *dnsserver)
|
||||
{
|
||||
if ((numdns < DNS_MAX_SERVERS) && (dns_pcb != NULL) &&
|
||||
(dnsserver != NULL) && (dnsserver->addr !=0 )) {
|
||||
(dnsserver != NULL) && !ip_addr_isany(dnsserver)) {
|
||||
dns_servers[numdns] = (*dnsserver);
|
||||
}
|
||||
}
|
||||
@@ -305,7 +285,7 @@ dns_setserver(u8_t numdns, struct ip_addr *dnsserver)
|
||||
* @return IP address of the indexed DNS server or "ip_addr_any" if the DNS
|
||||
* server has not been configured.
|
||||
*/
|
||||
struct ip_addr
|
||||
ip_addr_t
|
||||
dns_getserver(u8_t numdns)
|
||||
{
|
||||
if (numdns < DNS_MAX_SERVERS) {
|
||||
@@ -337,12 +317,18 @@ dns_init_local()
|
||||
struct local_hostlist_entry *entry;
|
||||
/* Dynamic: copy entries from DNS_LOCAL_HOSTLIST_INIT to list */
|
||||
struct local_hostlist_entry local_hostlist_init[] = DNS_LOCAL_HOSTLIST_INIT;
|
||||
size_t namelen;
|
||||
for (i = 0; i < sizeof(local_hostlist_init) / sizeof(struct local_hostlist_entry); i++) {
|
||||
entry = mem_malloc(sizeof(struct local_hostlist_entry));
|
||||
struct local_hostlist_entry *init_entry = &local_hostlist_init[i];
|
||||
LWIP_ASSERT("invalid host name (NULL)", init_entry->name != NULL);
|
||||
namelen = strlen(init_entry->name);
|
||||
LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN);
|
||||
entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST);
|
||||
LWIP_ASSERT("mem-error in dns_init_local", entry != NULL);
|
||||
if (entry != NULL) {
|
||||
struct local_hostlist_entry *init_entry = &local_hostlist_init[i];
|
||||
entry->name = init_entry->name;
|
||||
entry->name = (char*)entry + sizeof(struct local_hostlist_entry);
|
||||
MEMCPY((char*)entry->name, init_entry->name, namelen);
|
||||
((char*)entry->name)[namelen] = 0;
|
||||
entry->addr = init_entry->addr;
|
||||
entry->next = local_hostlist_dynamic;
|
||||
local_hostlist_dynamic = entry;
|
||||
@@ -356,7 +342,7 @@ dns_init_local()
|
||||
*
|
||||
* @param hostname Hostname to look for in the local host-list
|
||||
* @return The first IP address for the hostname in the local host-list or
|
||||
* INADDR_NONE if not found.
|
||||
* IPADDR_NONE if not found.
|
||||
*/
|
||||
static u32_t
|
||||
dns_lookup_local(const char *hostname)
|
||||
@@ -365,7 +351,7 @@ dns_lookup_local(const char *hostname)
|
||||
struct local_hostlist_entry *entry = local_hostlist_dynamic;
|
||||
while(entry != NULL) {
|
||||
if(strcmp(entry->name, hostname) == 0) {
|
||||
return entry->addr;
|
||||
return ip4_addr_get_u32(&entry->addr);
|
||||
}
|
||||
entry = entry->next;
|
||||
}
|
||||
@@ -373,11 +359,11 @@ dns_lookup_local(const char *hostname)
|
||||
int i;
|
||||
for (i = 0; i < sizeof(local_hostlist_static) / sizeof(struct local_hostlist_entry); i++) {
|
||||
if(strcmp(local_hostlist_static[i].name, hostname) == 0) {
|
||||
return local_hostlist_static[i].addr;
|
||||
return ip4_addr_get_u32(&local_hostlist_static[i].addr);
|
||||
}
|
||||
}
|
||||
#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
|
||||
return INADDR_NONE;
|
||||
return IPADDR_NONE;
|
||||
}
|
||||
|
||||
#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
|
||||
@@ -390,14 +376,14 @@ dns_lookup_local(const char *hostname)
|
||||
* @return the number of removed entries
|
||||
*/
|
||||
int
|
||||
dns_local_removehost(const char *hostname, const struct ip_addr *addr)
|
||||
dns_local_removehost(const char *hostname, const ip_addr_t *addr)
|
||||
{
|
||||
int removed = 0;
|
||||
struct local_hostlist_entry *entry = local_hostlist_dynamic;
|
||||
struct local_hostlist_entry *last_entry = NULL;
|
||||
while (entry != NULL) {
|
||||
if (((hostname == NULL) || !strcmp(entry->name, hostname)) &&
|
||||
((addr == NULL) || (entry->addr == addr->addr))) {
|
||||
((addr == NULL) || ip_addr_cmp(&entry->addr, addr))) {
|
||||
struct local_hostlist_entry *free_entry;
|
||||
if (last_entry != NULL) {
|
||||
last_entry->next = entry->next;
|
||||
@@ -406,7 +392,7 @@ dns_local_removehost(const char *hostname, const struct ip_addr *addr)
|
||||
}
|
||||
free_entry = entry;
|
||||
entry = entry->next;
|
||||
mem_free(free_entry);
|
||||
memp_free(MEMP_LOCALHOSTLIST, free_entry);
|
||||
removed++;
|
||||
} else {
|
||||
last_entry = entry;
|
||||
@@ -425,15 +411,21 @@ dns_local_removehost(const char *hostname, const struct ip_addr *addr)
|
||||
* @return ERR_OK if succeeded or ERR_MEM on memory error
|
||||
*/
|
||||
err_t
|
||||
dns_local_addhost(const char *hostname, const struct ip_addr *addr)
|
||||
dns_local_addhost(const char *hostname, const ip_addr_t *addr)
|
||||
{
|
||||
struct local_hostlist_entry *entry;
|
||||
entry = mem_malloc(sizeof(struct local_hostlist_entry));
|
||||
size_t namelen;
|
||||
LWIP_ASSERT("invalid host name (NULL)", hostname != NULL);
|
||||
namelen = strlen(hostname);
|
||||
LWIP_ASSERT("namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN", namelen <= DNS_LOCAL_HOSTLIST_MAX_NAMELEN);
|
||||
entry = (struct local_hostlist_entry *)memp_malloc(MEMP_LOCALHOSTLIST);
|
||||
if (entry == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
entry->name = hostname;
|
||||
entry->addr = addr->addr;
|
||||
entry->name = (char*)entry + sizeof(struct local_hostlist_entry);
|
||||
MEMCPY((char*)entry->name, hostname, namelen);
|
||||
((char*)entry->name)[namelen] = 0;
|
||||
ip_addr_copy(entry->addr, *addr);
|
||||
entry->next = local_hostlist_dynamic;
|
||||
local_hostlist_dynamic = entry;
|
||||
return ERR_OK;
|
||||
@@ -450,8 +442,8 @@ dns_local_addhost(const char *hostname, const struct ip_addr *addr)
|
||||
* for a hostname.
|
||||
*
|
||||
* @param name the hostname to look up
|
||||
* @return the hostname's IP address, as u32_t (instead of struct ip_addr to
|
||||
* better check for failure: != INADDR_NONE) or INADDR_NONE if the hostname
|
||||
* @return the hostname's IP address, as u32_t (instead of ip_addr_t to
|
||||
* better check for failure: != IPADDR_NONE) or IPADDR_NONE if the hostname
|
||||
* was not found in the cached dns_table.
|
||||
*/
|
||||
static u32_t
|
||||
@@ -462,12 +454,12 @@ dns_lookup(const char *name)
|
||||
u32_t addr;
|
||||
#endif /* DNS_LOCAL_HOSTLIST || defined(DNS_LOOKUP_LOCAL_EXTERN) */
|
||||
#if DNS_LOCAL_HOSTLIST
|
||||
if ((addr = dns_lookup_local(name)) != INADDR_NONE) {
|
||||
if ((addr = dns_lookup_local(name)) != IPADDR_NONE) {
|
||||
return addr;
|
||||
}
|
||||
#endif /* DNS_LOCAL_HOSTLIST */
|
||||
#ifdef DNS_LOOKUP_LOCAL_EXTERN
|
||||
if((addr = DNS_LOOKUP_LOCAL_EXTERN(name)) != INADDR_NONE) {
|
||||
if((addr = DNS_LOOKUP_LOCAL_EXTERN(name)) != IPADDR_NONE) {
|
||||
return addr;
|
||||
}
|
||||
#endif /* DNS_LOOKUP_LOCAL_EXTERN */
|
||||
@@ -479,11 +471,11 @@ dns_lookup(const char *name)
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("dns_lookup: \"%s\": found = ", name));
|
||||
ip_addr_debug_print(DNS_DEBUG, &(dns_table[i].ipaddr));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("\n"));
|
||||
return dns_table[i].ipaddr.addr;
|
||||
return ip4_addr_get_u32(&dns_table[i].ipaddr);
|
||||
}
|
||||
}
|
||||
|
||||
return INADDR_NONE;
|
||||
return IPADDR_NONE;
|
||||
}
|
||||
|
||||
#if DNS_DOES_NAME_CHECK
|
||||
@@ -578,7 +570,7 @@ dns_send(u8_t numdns, const char* name, u8_t id)
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("dns_send: dns_servers[%"U16_F"] \"%s\": request\n",
|
||||
(u16_t)(numdns), name));
|
||||
LWIP_ASSERT("dns server out of array", numdns < DNS_MAX_SERVERS);
|
||||
LWIP_ASSERT("dns server has no IP address set", dns_servers[numdns].addr != 0);
|
||||
LWIP_ASSERT("dns server has no IP address set", !ip_addr_isany(&dns_servers[numdns]));
|
||||
|
||||
/* if here, we have either a new query or a retry on a previous query to process */
|
||||
p = pbuf_alloc(PBUF_TRANSPORT, SIZEOF_DNS_HDR + DNS_MAX_NAME_LENGTH +
|
||||
@@ -590,7 +582,7 @@ dns_send(u8_t numdns, const char* name, u8_t id)
|
||||
memset(hdr, 0, SIZEOF_DNS_HDR);
|
||||
hdr->id = htons(id);
|
||||
hdr->flags1 = DNS_FLAG1_RD;
|
||||
hdr->numquestions = htons(1);
|
||||
hdr->numquestions = PP_HTONS(1);
|
||||
query = (char*)hdr + SIZEOF_DNS_HDR;
|
||||
pHostname = name;
|
||||
--pHostname;
|
||||
@@ -610,12 +602,12 @@ dns_send(u8_t numdns, const char* name, u8_t id)
|
||||
*query++='\0';
|
||||
|
||||
/* fill dns query */
|
||||
qry.type = htons(DNS_RRTYPE_A);
|
||||
qry.class = htons(DNS_RRCLASS_IN);
|
||||
MEMCPY( query, &qry, SIZEOF_DNS_QUERY);
|
||||
qry.type = PP_HTONS(DNS_RRTYPE_A);
|
||||
qry.cls = PP_HTONS(DNS_RRCLASS_IN);
|
||||
SMEMCPY(query, &qry, SIZEOF_DNS_QUERY);
|
||||
|
||||
/* resize pbuf to the exact dns query */
|
||||
pbuf_realloc(p, (query + SIZEOF_DNS_QUERY) - ((char*)(p->payload)));
|
||||
pbuf_realloc(p, (u16_t)((query + SIZEOF_DNS_QUERY) - ((char*)(p->payload))));
|
||||
|
||||
/* connect to the server for faster receiving */
|
||||
udp_connect(dns_pcb, &dns_servers[numdns], DNS_SERVER_PORT);
|
||||
@@ -643,6 +635,7 @@ dns_send(u8_t numdns, const char* name, u8_t id)
|
||||
static void
|
||||
dns_check_entry(u8_t i)
|
||||
{
|
||||
err_t err;
|
||||
struct dns_table_entry *pEntry = &dns_table[i];
|
||||
|
||||
LWIP_ASSERT("array index out of bounds", i < DNS_TABLE_SIZE);
|
||||
@@ -657,14 +650,18 @@ dns_check_entry(u8_t i)
|
||||
pEntry->retries = 0;
|
||||
|
||||
/* send DNS packet for this entry */
|
||||
dns_send(pEntry->numdns, pEntry->name, i);
|
||||
err = dns_send(pEntry->numdns, pEntry->name, i);
|
||||
if (err != ERR_OK) {
|
||||
LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING,
|
||||
("dns_send returned error: %s\n", lwip_strerr(err)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case DNS_STATE_ASKING: {
|
||||
if (--pEntry->tmr == 0) {
|
||||
if (++pEntry->retries == DNS_MAX_RETRIES) {
|
||||
if ((pEntry->numdns+1<DNS_MAX_SERVERS) && (dns_servers[pEntry->numdns+1].addr!=0)) {
|
||||
if ((pEntry->numdns+1<DNS_MAX_SERVERS) && !ip_addr_isany(&dns_servers[pEntry->numdns+1])) {
|
||||
/* change of server */
|
||||
pEntry->numdns++;
|
||||
pEntry->tmr = 1;
|
||||
@@ -686,7 +683,11 @@ dns_check_entry(u8_t i)
|
||||
pEntry->tmr = pEntry->retries;
|
||||
|
||||
/* send DNS packet for this entry */
|
||||
dns_send(pEntry->numdns, pEntry->name, i);
|
||||
err = dns_send(pEntry->numdns, pEntry->name, i);
|
||||
if (err != ERR_OK) {
|
||||
LWIP_DEBUGF(DNS_DEBUG | LWIP_DBG_LEVEL_WARNING,
|
||||
("dns_send returned error: %s\n", lwip_strerr(err)));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -729,20 +730,14 @@ dns_check_entries(void)
|
||||
* @params see udp.h
|
||||
*/
|
||||
static void
|
||||
dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
|
||||
dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
|
||||
{
|
||||
u8_t i;
|
||||
u16_t i;
|
||||
char *pHostname;
|
||||
struct dns_hdr *hdr;
|
||||
struct dns_answer ans;
|
||||
struct dns_table_entry *pEntry;
|
||||
u8_t nquestions, nanswers;
|
||||
#if (DNS_USES_STATIC_BUF == 0)
|
||||
u8_t dns_payload[DNS_MSG_SIZE];
|
||||
#endif /* (DNS_USES_STATIC_BUF == 0) */
|
||||
#if (DNS_USES_STATIC_BUF == 2)
|
||||
u8_t* dns_payload;
|
||||
#endif /* (DNS_USES_STATIC_BUF == 2) */
|
||||
u16_t nquestions, nanswers;
|
||||
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
LWIP_UNUSED_ARG(pcb);
|
||||
@@ -753,25 +748,16 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u
|
||||
if (p->tot_len > DNS_MSG_SIZE) {
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too big\n"));
|
||||
/* free pbuf and return */
|
||||
goto memerr1;
|
||||
goto memerr;
|
||||
}
|
||||
|
||||
/* is the dns message big enough ? */
|
||||
if (p->tot_len < (SIZEOF_DNS_HDR + SIZEOF_DNS_QUERY + SIZEOF_DNS_ANSWER)) {
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: pbuf too small\n"));
|
||||
/* free pbuf and return */
|
||||
goto memerr1;
|
||||
goto memerr;
|
||||
}
|
||||
|
||||
#if (DNS_USES_STATIC_BUF == 2)
|
||||
dns_payload = mem_malloc(p->tot_len);
|
||||
if (dns_payload == NULL) {
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: mem_malloc error\n"));
|
||||
/* free pbuf and return */
|
||||
goto memerr1;
|
||||
}
|
||||
#endif /* (DNS_USES_STATIC_BUF == 2) */
|
||||
|
||||
/* copy dns payload inside static buffer for processing */
|
||||
if (pbuf_copy_partial(p, dns_payload, p->tot_len, 0) == p->tot_len) {
|
||||
/* The ID in the DNS header should be our entry into the name table. */
|
||||
@@ -808,20 +794,21 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u
|
||||
/* Skip the name in the "question" part */
|
||||
pHostname = (char *) dns_parse_name((unsigned char *)dns_payload + SIZEOF_DNS_HDR) + SIZEOF_DNS_QUERY;
|
||||
|
||||
while(nanswers > 0) {
|
||||
while (nanswers > 0) {
|
||||
/* skip answer resource record's host name */
|
||||
pHostname = (char *) dns_parse_name((unsigned char *)pHostname);
|
||||
|
||||
/* Check for IP address type and Internet class. Others are discarded. */
|
||||
MEMCPY(&ans, pHostname, SIZEOF_DNS_ANSWER);
|
||||
if((ntohs(ans.type) == DNS_RRTYPE_A) && (ntohs(ans.class) == DNS_RRCLASS_IN) && (ntohs(ans.len) == sizeof(struct ip_addr)) ) {
|
||||
SMEMCPY(&ans, pHostname, SIZEOF_DNS_ANSWER);
|
||||
if((ans.type == PP_HTONS(DNS_RRTYPE_A)) && (ans.cls == PP_HTONS(DNS_RRCLASS_IN)) &&
|
||||
(ans.len == PP_HTONS(sizeof(ip_addr_t))) ) {
|
||||
/* read the answer resource record's TTL, and maximize it if needed */
|
||||
pEntry->ttl = ntohl(ans.ttl);
|
||||
if (pEntry->ttl > DNS_MAX_TTL) {
|
||||
pEntry->ttl = DNS_MAX_TTL;
|
||||
}
|
||||
/* read the IP address after answer resource record's header */
|
||||
MEMCPY( &(pEntry->ipaddr), (pHostname+SIZEOF_DNS_ANSWER), sizeof(struct ip_addr));
|
||||
SMEMCPY(&(pEntry->ipaddr), (pHostname+SIZEOF_DNS_ANSWER), sizeof(ip_addr_t));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("dns_recv: \"%s\": response = ", pEntry->name));
|
||||
ip_addr_debug_print(DNS_DEBUG, (&(pEntry->ipaddr)));
|
||||
LWIP_DEBUGF(DNS_DEBUG, ("\n"));
|
||||
@@ -830,7 +817,7 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u
|
||||
(*pEntry->found)(pEntry->name, &pEntry->ipaddr, pEntry->arg);
|
||||
}
|
||||
/* deallocate memory and return */
|
||||
goto memerr2;
|
||||
goto memerr;
|
||||
} else {
|
||||
pHostname = pHostname + SIZEOF_DNS_ANSWER + htons(ans.len);
|
||||
}
|
||||
@@ -844,7 +831,7 @@ dns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u
|
||||
}
|
||||
|
||||
/* deallocate memory and return */
|
||||
goto memerr2;
|
||||
goto memerr;
|
||||
|
||||
responseerr:
|
||||
/* ERROR: call specified callback function with NULL as name to indicate an error */
|
||||
@@ -855,13 +842,7 @@ responseerr:
|
||||
pEntry->state = DNS_STATE_UNUSED;
|
||||
pEntry->found = NULL;
|
||||
|
||||
memerr2:
|
||||
#if (DNS_USES_STATIC_BUF == 2)
|
||||
/* free dns buffer */
|
||||
mem_free(dns_payload);
|
||||
#endif /* (DNS_USES_STATIC_BUF == 2) */
|
||||
|
||||
memerr1:
|
||||
memerr:
|
||||
/* free pbuf */
|
||||
pbuf_free(p);
|
||||
return;
|
||||
@@ -881,6 +862,7 @@ dns_enqueue(const char *name, dns_found_callback found, void *callback_arg)
|
||||
u8_t i;
|
||||
u8_t lseq, lseqi;
|
||||
struct dns_table_entry *pEntry = NULL;
|
||||
size_t namelen;
|
||||
|
||||
/* search an unused entry, or the oldest one */
|
||||
lseq = lseqi = 0;
|
||||
@@ -920,7 +902,9 @@ dns_enqueue(const char *name, dns_found_callback found, void *callback_arg)
|
||||
pEntry->seqno = dns_seqno++;
|
||||
pEntry->found = found;
|
||||
pEntry->arg = callback_arg;
|
||||
strcpy(pEntry->name, name);
|
||||
namelen = LWIP_MIN(strlen(name), DNS_MAX_NAME_LENGTH-1);
|
||||
MEMCPY(pEntry->name, name, namelen);
|
||||
pEntry->name[namelen] = 0;
|
||||
|
||||
/* force to send query without waiting timer */
|
||||
dns_check_entry(i);
|
||||
@@ -938,9 +922,10 @@ dns_enqueue(const char *name, dns_found_callback found, void *callback_arg)
|
||||
* name is already in the local names table.
|
||||
* - ERR_INPROGRESS enqueue a request to be sent to the DNS server
|
||||
* for resolution if no errors are present.
|
||||
* - ERR_ARG: dns client not initialized or invalid hostname
|
||||
*
|
||||
* @param hostname the hostname that is to be queried
|
||||
* @param addr pointer to a struct ip_addr where to store the address if it is already
|
||||
* @param addr pointer to a ip_addr_t where to store the address if it is already
|
||||
* cached in the dns_table (only valid if ERR_OK is returned!)
|
||||
* @param found a callback function to be called on success, failure or timeout (only if
|
||||
* ERR_INPROGRESS is returned!)
|
||||
@@ -948,28 +933,33 @@ dns_enqueue(const char *name, dns_found_callback found, void *callback_arg)
|
||||
* @return a err_t return code.
|
||||
*/
|
||||
err_t
|
||||
dns_gethostbyname(const char *hostname, struct ip_addr *addr, dns_found_callback found,
|
||||
dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found,
|
||||
void *callback_arg)
|
||||
{
|
||||
u32_t ipaddr;
|
||||
/* not initialized or no valid server yet, or invalid addr pointer
|
||||
* or invalid hostname or invalid hostname length */
|
||||
if ((dns_pcb == NULL) || (addr == NULL) ||
|
||||
(!hostname) || (!hostname[0]) ||
|
||||
(strlen(hostname) >= DNS_MAX_NAME_LENGTH)) {
|
||||
return ERR_VAL;
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
#if LWIP_HAVE_LOOPIF
|
||||
if (strcmp(hostname,"localhost")==0) {
|
||||
addr->addr = htonl(INADDR_LOOPBACK);
|
||||
if (strcmp(hostname, "localhost")==0) {
|
||||
ip_addr_set_loopback(addr);
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif /* LWIP_HAVE_LOOPIF */
|
||||
|
||||
/* host name already in octet notation? set ip addr and return ERR_OK
|
||||
* already have this address cached? */
|
||||
if (((addr->addr = inet_addr(hostname)) != INADDR_NONE) ||
|
||||
((addr->addr = dns_lookup(hostname)) != INADDR_NONE)) {
|
||||
/* host name already in octet notation? set ip addr and return ERR_OK */
|
||||
ipaddr = ipaddr_addr(hostname);
|
||||
if (ipaddr == IPADDR_NONE) {
|
||||
/* already have this address cached? */
|
||||
ipaddr = dns_lookup(hostname);
|
||||
}
|
||||
if (ipaddr != IPADDR_NONE) {
|
||||
ip4_addr_set_u32(addr, ipaddr);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
170
src/core/init.c
170
src/core/init.c
@@ -49,12 +49,14 @@
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/raw.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/tcp_impl.h"
|
||||
#include "lwip/snmp_msg.h"
|
||||
#include "lwip/autoip.h"
|
||||
#include "lwip/igmp.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/timers.h"
|
||||
#include "netif/etharp.h"
|
||||
#include "lwip/api.h"
|
||||
|
||||
/* Compile-time sanity checks for configuration errors.
|
||||
* These can be done independently of LWIP_DEBUG, without penalty.
|
||||
@@ -65,9 +67,6 @@
|
||||
#if (!IP_SOF_BROADCAST && IP_SOF_BROADCAST_RECV)
|
||||
#error "If you want to use broadcast filter per pcb on recv operations, you have to define IP_SOF_BROADCAST=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (!LWIP_ARP && ARP_QUEUEING)
|
||||
#error "If you want to use ARP Queueing, you have to define LWIP_ARP=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (!LWIP_UDP && LWIP_UDPLITE)
|
||||
#error "If you want to use UDP Lite, you have to define LWIP_UDP=1 in your lwipopts.h"
|
||||
#endif
|
||||
@@ -80,12 +79,13 @@
|
||||
#if (!LWIP_UDP && LWIP_IGMP)
|
||||
#error "If you want to use IGMP, you have to define LWIP_UDP=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (!LWIP_UDP && LWIP_SNMP)
|
||||
#error "If you want to use SNMP, you have to define LWIP_UDP=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (!LWIP_UDP && LWIP_DNS)
|
||||
#error "If you want to use DNS, you have to define LWIP_UDP=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f))
|
||||
#error "If you want to use ARP, ARP_TABLE_SIZE must fit in an s8_t, so, you have to reduce it in your lwipopts.h"
|
||||
#endif
|
||||
#if !MEMP_MEM_MALLOC /* MEMP_NUM_* checks are disabled when not using the pool allocator */
|
||||
#if (LWIP_ARP && ARP_QUEUEING && (MEMP_NUM_ARP_QUEUE<=0))
|
||||
#error "If you want to use ARP Queueing, you have to define MEMP_NUM_ARP_QUEUE>=1 in your lwipopts.h"
|
||||
#endif
|
||||
@@ -98,33 +98,41 @@
|
||||
#if (LWIP_TCP && (MEMP_NUM_TCP_PCB<=0))
|
||||
#error "If you want to use TCP, you have to define MEMP_NUM_TCP_PCB>=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (LWIP_IGMP && (MEMP_NUM_IGMP_GROUP<=1))
|
||||
#error "If you want to use IGMP, you have to define MEMP_NUM_IGMP_GROUP>1 in your lwipopts.h"
|
||||
#endif
|
||||
#if ((LWIP_NETCONN || LWIP_SOCKET) && (MEMP_NUM_TCPIP_MSG_API<=0))
|
||||
#error "If you want to use Sequential API, you have to define MEMP_NUM_TCPIP_MSG_API>=1 in your lwipopts.h"
|
||||
#endif
|
||||
/* There must be sufficient timeouts, taking into account requirements of the subsystems. */
|
||||
#if LWIP_TIMERS && (MEMP_NUM_SYS_TIMEOUT < (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT))
|
||||
#error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts"
|
||||
#endif
|
||||
#if (IP_REASSEMBLY && (MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS))
|
||||
#error "MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS doesn't make sense since each struct ip_reassdata must hold 2 pbufs at least!"
|
||||
#endif
|
||||
#endif /* !MEMP_MEM_MALLOC */
|
||||
#if (LWIP_TCP && (TCP_WND > 0xffff))
|
||||
#error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h"
|
||||
#endif
|
||||
#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff))
|
||||
#error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h"
|
||||
#endif
|
||||
#if (LWIP_TCP && (TCP_SND_QUEUELEN < 2))
|
||||
#error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work"
|
||||
#endif
|
||||
#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12)))
|
||||
#error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h"
|
||||
#endif
|
||||
#if (LWIP_TCP && TCP_LISTEN_BACKLOG && (TCP_DEFAULT_LISTEN_BACKLOG < 0) || (TCP_DEFAULT_LISTEN_BACKLOG > 0xff))
|
||||
#error "If you want to use TCP backlog, TCP_DEFAULT_LISTEN_BACKLOG must fit into an u8_t"
|
||||
#endif
|
||||
#if (LWIP_IGMP && (MEMP_NUM_IGMP_GROUP<=1))
|
||||
#error "If you want to use IGMP, you have to define MEMP_NUM_IGMP_GROUP>1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (PPP_SUPPORT && (NO_SYS==1))
|
||||
#error "If you want to use PPP, you have to define NO_SYS=0 in your lwipopts.h"
|
||||
#endif
|
||||
#if (LWIP_NETIF_API && (NO_SYS==1))
|
||||
#error "If you want to use NETIF API, you have to define NO_SYS=0 in your lwipopts.h"
|
||||
#endif
|
||||
#if ((LWIP_SOCKET || LWIP_NETCONN) && (NO_SYS==1))
|
||||
#error "If you want to use Sequential API, you have to define NO_SYS=0 in your lwipopts.h"
|
||||
#endif
|
||||
#if ((LWIP_NETCONN || LWIP_SOCKET) && (MEMP_NUM_TCPIP_MSG_API<=0))
|
||||
#error "If you want to use Sequential API, you have to define MEMP_NUM_TCPIP_MSG_API>=1 in your lwipopts.h"
|
||||
#endif
|
||||
#if (!LWIP_NETCONN && LWIP_SOCKET)
|
||||
#error "If you want to use Socket API, you have to define LWIP_NETCONN=1 in your lwipopts.h"
|
||||
#endif
|
||||
@@ -146,13 +154,6 @@
|
||||
#if (LWIP_TCP && ((LWIP_EVENT_API && LWIP_CALLBACK_API) || (!LWIP_EVENT_API && !LWIP_CALLBACK_API)))
|
||||
#error "One and exactly one of LWIP_EVENT_API and LWIP_CALLBACK_API has to be enabled in your lwipopts.h"
|
||||
#endif
|
||||
/* There must be sufficient timeouts, taking into account requirements of the subsystems. */
|
||||
#if ((NO_SYS==0) && (MEMP_NUM_SYS_TIMEOUT < (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT)))
|
||||
#error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts"
|
||||
#endif
|
||||
#if (IP_REASSEMBLY && (MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS))
|
||||
#error "MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS doesn't make sense since each struct ip_reassdata must hold 2 pbufs at least!"
|
||||
#endif
|
||||
#if (MEM_LIBC_MALLOC && MEM_USE_POOLS)
|
||||
#error "MEM_LIBC_MALLOC and MEM_USE_POOLS may not both be simultaneously enabled in your lwipopts.h"
|
||||
#endif
|
||||
@@ -162,15 +163,53 @@
|
||||
#if (PBUF_POOL_BUFSIZE <= MEM_ALIGNMENT)
|
||||
#error "PBUF_POOL_BUFSIZE must be greater than MEM_ALIGNMENT or the offset may take the full first pbuf"
|
||||
#endif
|
||||
#if (TCP_QUEUE_OOSEQ && !LWIP_TCP)
|
||||
#error "TCP_QUEUE_OOSEQ requires LWIP_TCP"
|
||||
#endif
|
||||
#if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT)))
|
||||
#error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST"
|
||||
#endif
|
||||
#if PPP_SUPPORT && !PPPOS_SUPPORT & !PPPOE_SUPPORT
|
||||
#error "PPP_SUPPORT needs either PPPOS_SUPPORT or PPPOE_SUPPORT turned on"
|
||||
#endif
|
||||
#if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT)
|
||||
#error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT"
|
||||
#endif
|
||||
#if LWIP_IGMP && !defined(LWIP_RAND)
|
||||
#error "When using IGMP, LWIP_RAND() needs to be defined to a random-function returning an u32_t random value"
|
||||
#endif
|
||||
#if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING
|
||||
#error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too"
|
||||
#endif
|
||||
#if LWIP_TCP && LWIP_NETIF_TX_SINGLE_PBUF && !TCP_OVERSIZE
|
||||
#error "LWIP_NETIF_TX_SINGLE_PBUF needs TCP_OVERSIZE enabled to create single-pbuf TCP packets"
|
||||
#endif
|
||||
#if IP_FRAG && IP_FRAG_USES_STATIC_BUF && LWIP_NETIF_TX_SINGLE_PBUF
|
||||
#error "LWIP_NETIF_TX_SINGLE_PBUF does not work with IP_FRAG_USES_STATIC_BUF==1 as that creates pbuf queues"
|
||||
#endif
|
||||
#if LWIP_NETCONN && LWIP_TCP
|
||||
#if NETCONN_COPY != TCP_WRITE_FLAG_COPY
|
||||
#error "NETCONN_COPY != TCP_WRITE_FLAG_COPY"
|
||||
#endif
|
||||
#if NETCONN_MORE != TCP_WRITE_FLAG_MORE
|
||||
#error "NETCONN_MORE != TCP_WRITE_FLAG_MORE"
|
||||
#endif
|
||||
#endif /* LWIP_NETCONN && LWIP_TCP */
|
||||
#if LWIP_SOCKET
|
||||
/* Check that the SO_* socket options and SOF_* lwIP-internal flags match */
|
||||
#if SO_ACCEPTCONN != SOF_ACCEPTCONN
|
||||
#error "SO_ACCEPTCONN != SOF_ACCEPTCONN"
|
||||
#endif
|
||||
#if SO_REUSEADDR != SOF_REUSEADDR
|
||||
#error "WARNING: SO_REUSEADDR != SOF_REUSEADDR"
|
||||
#endif
|
||||
#if SO_KEEPALIVE != SOF_KEEPALIVE
|
||||
#error "WARNING: SO_KEEPALIVE != SOF_KEEPALIVE"
|
||||
#endif
|
||||
#if SO_BROADCAST != SOF_BROADCAST
|
||||
#error "WARNING: SO_BROADCAST != SOF_BROADCAST"
|
||||
#endif
|
||||
#if SO_LINGER != SOF_LINGER
|
||||
#error "WARNING: SO_LINGER != SOF_LINGER"
|
||||
#endif
|
||||
#endif /* LWIP_SOCKET */
|
||||
|
||||
|
||||
/* Compile-time checks for deprecated options.
|
||||
@@ -193,39 +232,55 @@
|
||||
#ifdef ETHARP_ALWAYS_INSERT
|
||||
#error "ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h."
|
||||
#endif
|
||||
#if SO_REUSE
|
||||
/* I removed the lot since this was an ugly hack. It broke the raw-API.
|
||||
It also came with many ugly goto's, Christiaan Simons. */
|
||||
#error "SO_REUSE currently unavailable, this was a hack"
|
||||
|
||||
#ifndef LWIP_DISABLE_TCP_SANITY_CHECKS
|
||||
#define LWIP_DISABLE_TCP_SANITY_CHECKS 0
|
||||
#endif
|
||||
#ifndef LWIP_DISABLE_MEMP_SANITY_CHECKS
|
||||
#define LWIP_DISABLE_MEMP_SANITY_CHECKS 0
|
||||
#endif
|
||||
|
||||
#ifdef LWIP_DEBUG
|
||||
static void
|
||||
lwip_sanity_check(void)
|
||||
{
|
||||
/* Warnings */
|
||||
/* MEMP sanity checks */
|
||||
#if !LWIP_DISABLE_MEMP_SANITY_CHECKS
|
||||
#if LWIP_NETCONN
|
||||
if (MEMP_NUM_NETCONN > (MEMP_NUM_TCP_PCB+MEMP_NUM_TCP_PCB_LISTEN+MEMP_NUM_UDP_PCB+MEMP_NUM_RAW_PCB))
|
||||
LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: MEMP_NUM_NETCONN should be less than the sum of MEMP_NUM_{TCP,RAW,UDP}_PCB+MEMP_NUM_TCP_PCB_LISTEN\n"));
|
||||
#if MEMP_MEM_MALLOC
|
||||
#if !MEMP_NUM_NETCONN && LWIP_SOCKET
|
||||
#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN cannot be 0 when using sockets!"
|
||||
#endif
|
||||
#else /* MEMP_MEM_MALLOC */
|
||||
#if MEMP_NUM_NETCONN > (MEMP_NUM_TCP_PCB+MEMP_NUM_TCP_PCB_LISTEN+MEMP_NUM_UDP_PCB+MEMP_NUM_RAW_PCB)
|
||||
#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN should be less than the sum of MEMP_NUM_{TCP,RAW,UDP}_PCB+MEMP_NUM_TCP_PCB_LISTEN. If you know what you are doing, define LWIP_DISABLE_MEMP_SANITY_CHECKS to 1 to disable this error."
|
||||
#endif
|
||||
#endif /* MEMP_MEM_MALLOC */
|
||||
#endif /* LWIP_NETCONN */
|
||||
#endif /* !LWIP_DISABLE_MEMP_SANITY_CHECKS */
|
||||
|
||||
/* TCP sanity checks */
|
||||
#if !LWIP_DISABLE_TCP_SANITY_CHECKS
|
||||
#if LWIP_TCP
|
||||
if (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN)
|
||||
LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN\n"));
|
||||
if (TCP_SND_BUF < 2 * TCP_MSS)
|
||||
LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly\n"));
|
||||
if (TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF/TCP_MSS)))
|
||||
LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work\n"));
|
||||
if (TCP_SNDLOWAT > TCP_SND_BUF)
|
||||
LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than or equal to TCP_SND_BUF.\n"));
|
||||
if (TCP_WND > (PBUF_POOL_SIZE*PBUF_POOL_BUFSIZE))
|
||||
LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE*PBUF_POOL_BUFSIZE\n"));
|
||||
if (TCP_WND < TCP_MSS)
|
||||
LWIP_PLATFORM_DIAG(("lwip_sanity_check: WARNING: TCP_WND is smaller than MSS\n"));
|
||||
#if !MEMP_MEM_MALLOC && (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN)
|
||||
#error "lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
||||
#endif
|
||||
#if TCP_SND_BUF < (2 * TCP_MSS)
|
||||
#error "lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
||||
#endif
|
||||
#if TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF / TCP_MSS))
|
||||
#error "lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
||||
#endif
|
||||
#if TCP_SNDLOWAT >= TCP_SND_BUF
|
||||
#error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than TCP_SND_BUF. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
||||
#endif
|
||||
#if TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN
|
||||
#error "lwip_sanity_check: WARNING: TCP_SNDQUEUELOWAT must be less than TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
||||
#endif
|
||||
#if !MEMP_MEM_MALLOC && (TCP_WND > (PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - (PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN))))
|
||||
#error "lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - protocol headers). If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
||||
#endif
|
||||
#if TCP_WND < TCP_MSS
|
||||
#error "lwip_sanity_check: WARNING: TCP_WND is smaller than MSS. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
|
||||
#endif
|
||||
#endif /* LWIP_TCP */
|
||||
}
|
||||
#else /* LWIP_DEBUG */
|
||||
#define lwip_sanity_check()
|
||||
#endif /* LWIP_DEBUG */
|
||||
#endif /* !LWIP_DISABLE_TCP_SANITY_CHECKS */
|
||||
|
||||
/**
|
||||
* Perform Sanity check of user-configurable values, and initialize all modules.
|
||||
@@ -233,12 +288,11 @@ lwip_sanity_check(void)
|
||||
void
|
||||
lwip_init(void)
|
||||
{
|
||||
/* Sanity check user-configurable values */
|
||||
lwip_sanity_check();
|
||||
|
||||
/* Modules initialization */
|
||||
stats_init();
|
||||
#if !NO_SYS
|
||||
sys_init();
|
||||
#endif /* !NO_SYS */
|
||||
mem_init();
|
||||
memp_init();
|
||||
pbuf_init();
|
||||
@@ -271,4 +325,8 @@ lwip_init(void)
|
||||
#if LWIP_DNS
|
||||
dns_init();
|
||||
#endif /* LWIP_DNS */
|
||||
|
||||
#if LWIP_TIMERS
|
||||
sys_timeouts_init();
|
||||
#endif /* LWIP_TIMERS */
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
static void autoip_handle_arp_conflict(struct netif *netif);
|
||||
|
||||
/* creates a pseudo random LL IP-Address for a network interface */
|
||||
static void autoip_create_addr(struct netif *netif, struct ip_addr *ipaddr);
|
||||
static void autoip_create_addr(struct netif *netif, ip_addr_t *ipaddr);
|
||||
|
||||
/* sends an ARP probe */
|
||||
static err_t autoip_arp_probe(struct netif *netif);
|
||||
@@ -122,13 +122,35 @@ static err_t autoip_bind(struct netif *netif);
|
||||
/* start sending probes for llipaddr */
|
||||
static void autoip_start_probing(struct netif *netif);
|
||||
|
||||
/**
|
||||
* Initialize this module
|
||||
|
||||
/** Set a statically allocated struct autoip to work with.
|
||||
* Using this prevents autoip_start to allocate it using mem_malloc.
|
||||
*
|
||||
* @param netif the netif for which to set the struct autoip
|
||||
* @param dhcp (uninitialised) dhcp struct allocated by the application
|
||||
*/
|
||||
void
|
||||
autoip_init(void)
|
||||
autoip_set_struct(struct netif *netif, struct autoip *autoip)
|
||||
{
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_init()\n"));
|
||||
LWIP_ASSERT("netif != NULL", netif != NULL);
|
||||
LWIP_ASSERT("autoip != NULL", autoip != NULL);
|
||||
LWIP_ASSERT("netif already has a struct autoip set", netif->autoip == NULL);
|
||||
|
||||
/* clear data structure */
|
||||
memset(autoip, 0, sizeof(struct autoip));
|
||||
/* autoip->state = AUTOIP_STATE_OFF; */
|
||||
netif->autoip = autoip;
|
||||
}
|
||||
|
||||
/** Restart AutoIP client and check the next address (conflict detected)
|
||||
*
|
||||
* @param netif The netif under AutoIP control
|
||||
*/
|
||||
static void
|
||||
autoip_restart(struct netif *netif)
|
||||
{
|
||||
netif->autoip->tried_llipaddr++;
|
||||
autoip_start(netif);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,8 +162,8 @@ autoip_handle_arp_conflict(struct netif *netif)
|
||||
/* Somehow detect if we are defending or retreating */
|
||||
unsigned char defend = 1; /* tbd */
|
||||
|
||||
if(defend) {
|
||||
if(netif->autoip->lastconflict > 0) {
|
||||
if (defend) {
|
||||
if (netif->autoip->lastconflict > 0) {
|
||||
/* retreat, there was a conflicting ARP in the last
|
||||
* DEFEND_INTERVAL seconds
|
||||
*/
|
||||
@@ -149,7 +171,7 @@ autoip_handle_arp_conflict(struct netif *netif)
|
||||
("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n"));
|
||||
|
||||
/* TODO: close all TCP sessions */
|
||||
autoip_start(netif);
|
||||
autoip_restart(netif);
|
||||
} else {
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||
("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n"));
|
||||
@@ -160,7 +182,7 @@ autoip_handle_arp_conflict(struct netif *netif)
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||
("autoip_handle_arp_conflict(): we do not defend, retreating\n"));
|
||||
/* TODO: close all TCP sessions */
|
||||
autoip_start(netif);
|
||||
autoip_restart(netif);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,7 +193,7 @@ autoip_handle_arp_conflict(struct netif *netif)
|
||||
* @param ipaddr ip address to initialize
|
||||
*/
|
||||
static void
|
||||
autoip_create_addr(struct netif *netif, struct ip_addr *ipaddr)
|
||||
autoip_create_addr(struct netif *netif, ip_addr_t *ipaddr)
|
||||
{
|
||||
/* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255
|
||||
* compliant to RFC 3927 Section 2.1
|
||||
@@ -190,11 +212,12 @@ autoip_create_addr(struct netif *netif, struct ip_addr *ipaddr)
|
||||
}
|
||||
LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) &&
|
||||
(addr <= AUTOIP_RANGE_END));
|
||||
ipaddr->addr = htonl(addr);
|
||||
ip4_addr_set_u32(ipaddr, htonl(addr));
|
||||
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||
("autoip_create_addr(): tried_llipaddr=%"U16_F", 0x%08"X32_F"\n",
|
||||
(u16_t)(netif->autoip->tried_llipaddr), (u32_t)(ipaddr->addr)));
|
||||
("autoip_create_addr(): tried_llipaddr=%"U16_F", %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
(u16_t)(netif->autoip->tried_llipaddr), ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr),
|
||||
ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,11 +255,13 @@ static err_t
|
||||
autoip_bind(struct netif *netif)
|
||||
{
|
||||
struct autoip *autoip = netif->autoip;
|
||||
struct ip_addr sn_mask, gw_addr;
|
||||
ip_addr_t sn_mask, gw_addr;
|
||||
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
|
||||
("autoip_bind(netif=%p) %c%c%"U16_F" 0x%08"X32_F"\n",
|
||||
(void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num, autoip->llipaddr.addr));
|
||||
("autoip_bind(netif=%p) %c%c%"U16_F" %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
(void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num,
|
||||
ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr),
|
||||
ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr)));
|
||||
|
||||
IP4_ADDR(&sn_mask, 255, 255, 0, 0);
|
||||
IP4_ADDR(&gw_addr, 0, 0, 0, 0);
|
||||
@@ -262,31 +287,31 @@ autoip_start(struct netif *netif)
|
||||
struct autoip *autoip = netif->autoip;
|
||||
err_t result = ERR_OK;
|
||||
|
||||
if(netif_is_up(netif)) {
|
||||
if (netif_is_up(netif)) {
|
||||
netif_set_down(netif);
|
||||
}
|
||||
|
||||
/* Set IP-Address, Netmask and Gateway to 0 to make sure that
|
||||
* ARP Packets are formed correctly
|
||||
*/
|
||||
netif->ip_addr.addr = 0;
|
||||
netif->netmask.addr = 0;
|
||||
netif->gw.addr = 0;
|
||||
ip_addr_set_zero(&netif->ip_addr);
|
||||
ip_addr_set_zero(&netif->netmask);
|
||||
ip_addr_set_zero(&netif->gw);
|
||||
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||
("autoip_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0],
|
||||
netif->name[1], (u16_t)netif->num));
|
||||
if(autoip == NULL) {
|
||||
if (autoip == NULL) {
|
||||
/* no AutoIP client attached yet? */
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
|
||||
("autoip_start(): starting new AUTOIP client\n"));
|
||||
autoip = mem_malloc(sizeof(struct autoip));
|
||||
if(autoip == NULL) {
|
||||
autoip = (struct autoip *)mem_malloc(sizeof(struct autoip));
|
||||
if (autoip == NULL) {
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
|
||||
("autoip_start(): could not allocate autoip\n"));
|
||||
return ERR_MEM;
|
||||
}
|
||||
memset( autoip, 0, sizeof(struct autoip));
|
||||
memset(autoip, 0, sizeof(struct autoip));
|
||||
/* store this AutoIP client in the netif */
|
||||
netif->autoip = autoip;
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip"));
|
||||
@@ -294,12 +319,11 @@ autoip_start(struct netif *netif)
|
||||
autoip->state = AUTOIP_STATE_OFF;
|
||||
autoip->ttw = 0;
|
||||
autoip->sent_num = 0;
|
||||
memset(&autoip->llipaddr, 0, sizeof(struct ip_addr));
|
||||
ip_addr_set_zero(&autoip->llipaddr);
|
||||
autoip->lastconflict = 0;
|
||||
}
|
||||
|
||||
autoip_create_addr(netif, &(autoip->llipaddr));
|
||||
autoip->tried_llipaddr++;
|
||||
autoip_start_probing(netif);
|
||||
|
||||
return result;
|
||||
@@ -312,6 +336,10 @@ autoip_start_probing(struct netif *netif)
|
||||
|
||||
autoip->state = AUTOIP_STATE_PROBING;
|
||||
autoip->sent_num = 0;
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||
("autoip_start_probing(): changing state to PROBING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr),
|
||||
ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr)));
|
||||
|
||||
/* time to wait to first probe, this is randomly
|
||||
* choosen out of 0 to PROBE_WAIT seconds.
|
||||
@@ -324,7 +352,7 @@ autoip_start_probing(struct netif *netif)
|
||||
* accquiring and probing address
|
||||
* compliant to RFC 3927 Section 2.2.1
|
||||
*/
|
||||
if(autoip->tried_llipaddr > MAX_CONFLICTS) {
|
||||
if (autoip->tried_llipaddr > MAX_CONFLICTS) {
|
||||
autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND;
|
||||
}
|
||||
}
|
||||
@@ -368,7 +396,7 @@ autoip_tmr()
|
||||
while (netif != NULL) {
|
||||
/* only act on AutoIP configured interfaces */
|
||||
if (netif->autoip != NULL) {
|
||||
if(netif->autoip->lastconflict > 0) {
|
||||
if (netif->autoip->lastconflict > 0) {
|
||||
netif->autoip->lastconflict--;
|
||||
}
|
||||
|
||||
@@ -378,13 +406,17 @@ autoip_tmr()
|
||||
|
||||
switch(netif->autoip->state) {
|
||||
case AUTOIP_STATE_PROBING:
|
||||
if(netif->autoip->ttw > 0) {
|
||||
if (netif->autoip->ttw > 0) {
|
||||
netif->autoip->ttw--;
|
||||
} else {
|
||||
if(netif->autoip->sent_num >= PROBE_NUM) {
|
||||
if (netif->autoip->sent_num >= PROBE_NUM) {
|
||||
netif->autoip->state = AUTOIP_STATE_ANNOUNCING;
|
||||
netif->autoip->sent_num = 0;
|
||||
netif->autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND;
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||
("autoip_tmr(): changing state to ANNOUNCING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr),
|
||||
ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr)));
|
||||
} else {
|
||||
autoip_arp_probe(netif);
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
|
||||
@@ -399,10 +431,10 @@ autoip_tmr()
|
||||
break;
|
||||
|
||||
case AUTOIP_STATE_ANNOUNCING:
|
||||
if(netif->autoip->ttw > 0) {
|
||||
if (netif->autoip->ttw > 0) {
|
||||
netif->autoip->ttw--;
|
||||
} else {
|
||||
if(netif->autoip->sent_num == 0) {
|
||||
if (netif->autoip->sent_num == 0) {
|
||||
/* We are here the first time, so we waited ANNOUNCE_WAIT seconds
|
||||
* Now we can bind to an IP address and use it.
|
||||
*
|
||||
@@ -418,10 +450,14 @@ autoip_tmr()
|
||||
netif->autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND;
|
||||
netif->autoip->sent_num++;
|
||||
|
||||
if(netif->autoip->sent_num >= ANNOUNCE_NUM) {
|
||||
if (netif->autoip->sent_num >= ANNOUNCE_NUM) {
|
||||
netif->autoip->state = AUTOIP_STATE_BOUND;
|
||||
netif->autoip->sent_num = 0;
|
||||
netif->autoip->ttw = 0;
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||
("autoip_tmr(): changing state to BOUND: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
ip4_addr1_16(&netif->autoip->llipaddr), ip4_addr2_16(&netif->autoip->llipaddr),
|
||||
ip4_addr3_16(&netif->autoip->llipaddr), ip4_addr4_16(&netif->autoip->llipaddr)));
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -448,20 +484,15 @@ autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
|
||||
* when probing ip.dst == llipaddr && hw.src != netif->hwaddr
|
||||
* we have a conflict and must solve it
|
||||
*/
|
||||
struct ip_addr sipaddr, dipaddr;
|
||||
ip_addr_t sipaddr, dipaddr;
|
||||
struct eth_addr netifaddr;
|
||||
netifaddr.addr[0] = netif->hwaddr[0];
|
||||
netifaddr.addr[1] = netif->hwaddr[1];
|
||||
netifaddr.addr[2] = netif->hwaddr[2];
|
||||
netifaddr.addr[3] = netif->hwaddr[3];
|
||||
netifaddr.addr[4] = netif->hwaddr[4];
|
||||
netifaddr.addr[5] = netif->hwaddr[5];
|
||||
ETHADDR16_COPY(netifaddr.addr, netif->hwaddr);
|
||||
|
||||
/* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
|
||||
* structure packing (not using structure copy which breaks strict-aliasing rules).
|
||||
*/
|
||||
SMEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));
|
||||
SMEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr));
|
||||
IPADDR2_COPY(&sipaddr, &hdr->sipaddr);
|
||||
IPADDR2_COPY(&dipaddr, &hdr->dipaddr);
|
||||
|
||||
if ((netif->autoip->state == AUTOIP_STATE_PROBING) ||
|
||||
((netif->autoip->state == AUTOIP_STATE_ANNOUNCING) &&
|
||||
@@ -477,7 +508,7 @@ autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
|
||||
!eth_addr_cmp(&netifaddr, &hdr->shwaddr))) {
|
||||
LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
|
||||
("autoip_arp_reply(): Probe Conflict detected\n"));
|
||||
autoip_start(netif);
|
||||
autoip_restart(netif);
|
||||
}
|
||||
} else {
|
||||
/* RFC 3927 Section 2.5:
|
||||
|
||||
@@ -44,7 +44,6 @@
|
||||
#if LWIP_ICMP /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/icmp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/def.h"
|
||||
@@ -83,14 +82,13 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
||||
#endif /* LWIP_DEBUG */
|
||||
struct icmp_echo_hdr *iecho;
|
||||
struct ip_hdr *iphdr;
|
||||
struct ip_addr tmpaddr;
|
||||
s16_t hlen;
|
||||
|
||||
ICMP_STATS_INC(icmp.recv);
|
||||
snmp_inc_icmpinmsgs();
|
||||
|
||||
|
||||
iphdr = p->payload;
|
||||
iphdr = (struct ip_hdr *)p->payload;
|
||||
hlen = IPH_HL(iphdr) * 4;
|
||||
if (pbuf_header(p, -hlen) || (p->tot_len < sizeof(u16_t)*2)) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len));
|
||||
@@ -102,19 +100,23 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
||||
code = *(((u8_t *)p->payload)+1);
|
||||
#endif /* LWIP_DEBUG */
|
||||
switch (type) {
|
||||
case ICMP_ER:
|
||||
/* This is OK, echo reply might have been parsed by a raw PCB
|
||||
(as obviously, an echo request has been sent, too). */
|
||||
break;
|
||||
case ICMP_ECHO:
|
||||
#if !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING
|
||||
{
|
||||
int accepted = 1;
|
||||
#if !LWIP_MULTICAST_PING
|
||||
/* multicast destination address? */
|
||||
if (ip_addr_ismulticast(&iphdr->dest)) {
|
||||
if (ip_addr_ismulticast(¤t_iphdr_dest)) {
|
||||
accepted = 0;
|
||||
}
|
||||
#endif /* LWIP_MULTICAST_PING */
|
||||
#if !LWIP_BROADCAST_PING
|
||||
/* broadcast destination address? */
|
||||
if (ip_addr_isbroadcast(&iphdr->dest, inp)) {
|
||||
if (ip_addr_isbroadcast(¤t_iphdr_dest, inp)) {
|
||||
accepted = 0;
|
||||
}
|
||||
#endif /* LWIP_BROADCAST_PING */
|
||||
@@ -163,7 +165,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
||||
LWIP_ASSERT("icmp_input: copying to new pbuf failed\n", 0);
|
||||
goto memerr;
|
||||
}
|
||||
iphdr = r->payload;
|
||||
iphdr = (struct ip_hdr *)r->payload;
|
||||
/* switch r->payload back to icmp header */
|
||||
if (pbuf_header(r, -hlen)) {
|
||||
LWIP_ASSERT("icmp_input: restoring original p->payload failed\n", 0);
|
||||
@@ -184,17 +186,20 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
||||
/* At this point, all checks are OK. */
|
||||
/* We generate an answer by switching the dest and src ip addresses,
|
||||
* setting the icmp type to ECHO_RESPONSE and updating the checksum. */
|
||||
iecho = p->payload;
|
||||
tmpaddr.addr = iphdr->src.addr;
|
||||
iphdr->src.addr = iphdr->dest.addr;
|
||||
iphdr->dest.addr = tmpaddr.addr;
|
||||
iecho = (struct icmp_echo_hdr *)p->payload;
|
||||
ip_addr_copy(iphdr->src, *ip_current_dest_addr());
|
||||
ip_addr_copy(iphdr->dest, *ip_current_src_addr());
|
||||
ICMPH_TYPE_SET(iecho, ICMP_ER);
|
||||
#if CHECKSUM_GEN_ICMP
|
||||
/* adjust the checksum */
|
||||
if (iecho->chksum >= htons(0xffff - (ICMP_ECHO << 8))) {
|
||||
iecho->chksum += htons(ICMP_ECHO << 8) + 1;
|
||||
if (iecho->chksum >= PP_HTONS(0xffffU - (ICMP_ECHO << 8))) {
|
||||
iecho->chksum += PP_HTONS(ICMP_ECHO << 8) + 1;
|
||||
} else {
|
||||
iecho->chksum += htons(ICMP_ECHO << 8);
|
||||
iecho->chksum += PP_HTONS(ICMP_ECHO << 8);
|
||||
}
|
||||
#else /* CHECKSUM_GEN_ICMP */
|
||||
iecho->chksum = 0;
|
||||
#endif /* CHECKSUM_GEN_ICMP */
|
||||
|
||||
/* Set the correct TTL and recalculate the header checksum. */
|
||||
IPH_TTL_SET(iphdr, ICMP_TTL);
|
||||
@@ -213,7 +218,8 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
||||
LWIP_ASSERT("Can't move over header in packet", 0);
|
||||
} else {
|
||||
err_t ret;
|
||||
ret = ip_output_if(p, &(iphdr->src), IP_HDRINCL,
|
||||
/* send an ICMP packet, src addr is the dest addr of the curren packet */
|
||||
ret = ip_output_if(p, ip_current_dest_addr(), IP_HDRINCL,
|
||||
ICMP_TTL, 0, IP_PROTO_ICMP, inp);
|
||||
if (ret != ERR_OK) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ip_output_if returned an error: %c.\n", ret));
|
||||
@@ -288,6 +294,7 @@ icmp_send_response(struct pbuf *p, u8_t type, u8_t code)
|
||||
struct ip_hdr *iphdr;
|
||||
/* we can use the echo header here */
|
||||
struct icmp_echo_hdr *icmphdr;
|
||||
ip_addr_t iphdr_src;
|
||||
|
||||
/* ICMP header + IP header + 8 bytes of data */
|
||||
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
|
||||
@@ -299,14 +306,14 @@ icmp_send_response(struct pbuf *p, u8_t type, u8_t code)
|
||||
LWIP_ASSERT("check that first pbuf can hold icmp message",
|
||||
(q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE)));
|
||||
|
||||
iphdr = p->payload;
|
||||
iphdr = (struct ip_hdr *)p->payload;
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
|
||||
ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src));
|
||||
LWIP_DEBUGF(ICMP_DEBUG, (" to "));
|
||||
ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest));
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("\n"));
|
||||
|
||||
icmphdr = q->payload;
|
||||
icmphdr = (struct icmp_echo_hdr *)q->payload;
|
||||
icmphdr->type = type;
|
||||
icmphdr->code = code;
|
||||
icmphdr->id = 0;
|
||||
@@ -324,7 +331,8 @@ icmp_send_response(struct pbuf *p, u8_t type, u8_t code)
|
||||
snmp_inc_icmpoutmsgs();
|
||||
/* increase number of destination unreachable messages attempted to send */
|
||||
snmp_inc_icmpouttimeexcds();
|
||||
ip_output(q, NULL, &(iphdr->src), ICMP_TTL, 0, IP_PROTO_ICMP);
|
||||
ip_addr_copy(iphdr_src, iphdr->src);
|
||||
ip_output(q, NULL, &iphdr_src, ICMP_TTL, 0, IP_PROTO_ICMP);
|
||||
pbuf_free(q);
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,6 @@ Steve Reynolds
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/icmp.h"
|
||||
@@ -96,13 +95,59 @@ Steve Reynolds
|
||||
|
||||
#include "string.h"
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Globales
|
||||
*----------------------------------------------------------------------------*/
|
||||
/*
|
||||
* IGMP constants
|
||||
*/
|
||||
#define IGMP_TTL 1
|
||||
#define IGMP_MINLEN 8
|
||||
#define ROUTER_ALERT 0x9404U
|
||||
#define ROUTER_ALERTLEN 4
|
||||
|
||||
/*
|
||||
* IGMP message types, including version number.
|
||||
*/
|
||||
#define IGMP_MEMB_QUERY 0x11 /* Membership query */
|
||||
#define IGMP_V1_MEMB_REPORT 0x12 /* Ver. 1 membership report */
|
||||
#define IGMP_V2_MEMB_REPORT 0x16 /* Ver. 2 membership report */
|
||||
#define IGMP_LEAVE_GROUP 0x17 /* Leave-group message */
|
||||
|
||||
/* Group membership states */
|
||||
#define IGMP_GROUP_NON_MEMBER 0
|
||||
#define IGMP_GROUP_DELAYING_MEMBER 1
|
||||
#define IGMP_GROUP_IDLE_MEMBER 2
|
||||
|
||||
/**
|
||||
* IGMP packet format.
|
||||
*/
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct igmp_msg {
|
||||
PACK_STRUCT_FIELD(u8_t igmp_msgtype);
|
||||
PACK_STRUCT_FIELD(u8_t igmp_maxresp);
|
||||
PACK_STRUCT_FIELD(u16_t igmp_checksum);
|
||||
PACK_STRUCT_FIELD(ip_addr_p_t igmp_group_address);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
|
||||
static struct igmp_group *igmp_lookup_group(struct netif *ifp, ip_addr_t *addr);
|
||||
static err_t igmp_remove_group(struct igmp_group *group);
|
||||
static void igmp_timeout( struct igmp_group *group);
|
||||
static void igmp_start_timer(struct igmp_group *group, u8_t max_time);
|
||||
static void igmp_delaying_member(struct igmp_group *group, u8_t maxresp);
|
||||
static err_t igmp_ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, struct netif *netif);
|
||||
static void igmp_send(struct igmp_group *group, u8_t type);
|
||||
|
||||
|
||||
static struct igmp_group* igmp_group_list;
|
||||
static struct ip_addr allsystems;
|
||||
static struct ip_addr allrouters;
|
||||
static ip_addr_t allsystems;
|
||||
static ip_addr_t allrouters;
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the IGMP module
|
||||
@@ -128,7 +173,7 @@ igmp_dump_group_list()
|
||||
while (group != NULL) {
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_dump_group_list: [%"U32_F"] ", (u32_t)(group->group_state)));
|
||||
ip_addr_debug_print(IGMP_DEBUG, &group->group_address);
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->interface));
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->netif));
|
||||
group = group->next;
|
||||
}
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("\n"));
|
||||
@@ -160,7 +205,7 @@ igmp_start(struct netif *netif)
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_start: igmp_mac_filter(ADD "));
|
||||
ip_addr_debug_print(IGMP_DEBUG, &allsystems);
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (") on if %p\n", netif));
|
||||
netif->igmp_mac_filter( netif, &allsystems, IGMP_ADD_MAC_FILTER);
|
||||
netif->igmp_mac_filter(netif, &allsystems, IGMP_ADD_MAC_FILTER);
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
@@ -185,7 +230,7 @@ igmp_stop(struct netif *netif)
|
||||
while (group != NULL) {
|
||||
next = group->next;
|
||||
/* is it a group joined on this interface? */
|
||||
if (group->interface == netif) {
|
||||
if (group->netif == netif) {
|
||||
/* is it the first group of the list? */
|
||||
if (group == igmp_group_list) {
|
||||
igmp_group_list = next;
|
||||
@@ -219,15 +264,15 @@ igmp_stop(struct netif *netif)
|
||||
* @param netif network interface on which report IGMP memberships
|
||||
*/
|
||||
void
|
||||
igmp_report_groups( struct netif *netif)
|
||||
igmp_report_groups(struct netif *netif)
|
||||
{
|
||||
struct igmp_group *group = igmp_group_list;
|
||||
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %p\n", netif));
|
||||
|
||||
while (group != NULL) {
|
||||
if (group->interface == netif) {
|
||||
igmp_delaying_member( group, IGMP_JOIN_DELAYING_MEMBER_TMR);
|
||||
if (group->netif == netif) {
|
||||
igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR);
|
||||
}
|
||||
group = group->next;
|
||||
}
|
||||
@@ -242,12 +287,12 @@ igmp_report_groups( struct netif *netif)
|
||||
* NULL if the group wasn't found.
|
||||
*/
|
||||
struct igmp_group *
|
||||
igmp_lookfor_group(struct netif *ifp, struct ip_addr *addr)
|
||||
igmp_lookfor_group(struct netif *ifp, ip_addr_t *addr)
|
||||
{
|
||||
struct igmp_group *group = igmp_group_list;
|
||||
|
||||
while (group != NULL) {
|
||||
if ((group->interface == ifp) && (ip_addr_cmp(&(group->group_address), addr))) {
|
||||
if ((group->netif == ifp) && (ip_addr_cmp(&(group->group_address), addr))) {
|
||||
return group;
|
||||
}
|
||||
group = group->next;
|
||||
@@ -268,7 +313,7 @@ igmp_lookfor_group(struct netif *ifp, struct ip_addr *addr)
|
||||
* NULL on memory error.
|
||||
*/
|
||||
struct igmp_group *
|
||||
igmp_lookup_group(struct netif *ifp, struct ip_addr *addr)
|
||||
igmp_lookup_group(struct netif *ifp, ip_addr_t *addr)
|
||||
{
|
||||
struct igmp_group *group = igmp_group_list;
|
||||
|
||||
@@ -280,9 +325,9 @@ igmp_lookup_group(struct netif *ifp, struct ip_addr *addr)
|
||||
}
|
||||
|
||||
/* Group doesn't exist yet, create a new one */
|
||||
group = memp_malloc(MEMP_IGMP_GROUP);
|
||||
group = (struct igmp_group *)memp_malloc(MEMP_IGMP_GROUP);
|
||||
if (group != NULL) {
|
||||
group->interface = ifp;
|
||||
group->netif = ifp;
|
||||
ip_addr_set(&(group->group_address), addr);
|
||||
group->timer = 0; /* Not running */
|
||||
group->group_state = IGMP_GROUP_NON_MEMBER;
|
||||
@@ -306,7 +351,7 @@ igmp_lookup_group(struct netif *ifp, struct ip_addr *addr)
|
||||
* @param group the group to remove from the global igmp_group_list
|
||||
* @return ERR_OK if group was removed from the list, an err_t otherwise
|
||||
*/
|
||||
err_t
|
||||
static err_t
|
||||
igmp_remove_group(struct igmp_group *group)
|
||||
{
|
||||
err_t err = ERR_OK;
|
||||
@@ -341,15 +386,17 @@ igmp_remove_group(struct igmp_group *group)
|
||||
* @param dest destination ip address of the igmp packet
|
||||
*/
|
||||
void
|
||||
igmp_input(struct pbuf *p, struct netif *inp, struct ip_addr *dest)
|
||||
igmp_input(struct pbuf *p, struct netif *inp, ip_addr_t *dest)
|
||||
{
|
||||
struct ip_hdr * iphdr;
|
||||
struct igmp_msg* igmp;
|
||||
struct igmp_group* group;
|
||||
struct igmp_group* groupref;
|
||||
|
||||
IGMP_STATS_INC(igmp.recv);
|
||||
|
||||
/* Note that the length CAN be greater than 8 but only 8 are used - All are included in the checksum */
|
||||
iphdr = p->payload;
|
||||
iphdr = (struct ip_hdr *)p->payload;
|
||||
if (pbuf_header(p, -(s16_t)(IPH_HL(iphdr) * 4)) || (p->len < IGMP_MINLEN)) {
|
||||
pbuf_free(p);
|
||||
IGMP_STATS_INC(igmp.lenerr);
|
||||
@@ -373,11 +420,12 @@ igmp_input(struct pbuf *p, struct netif *inp, struct ip_addr *dest)
|
||||
}
|
||||
|
||||
/* Packet is ok so find an existing group */
|
||||
group = igmp_lookfor_group(inp, dest); /* use the incoming IP address! */
|
||||
group = igmp_lookfor_group(inp, dest); /* use the destination IP address of incoming packet */
|
||||
|
||||
/* If group can be found or create... */
|
||||
if (!group) {
|
||||
pbuf_free(p);
|
||||
IGMP_STATS_INC(igmp.drop);
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP frame not for us\n"));
|
||||
return;
|
||||
}
|
||||
@@ -386,50 +434,56 @@ igmp_input(struct pbuf *p, struct netif *inp, struct ip_addr *dest)
|
||||
switch (igmp->igmp_msgtype) {
|
||||
case IGMP_MEMB_QUERY: {
|
||||
/* IGMP_MEMB_QUERY to the "all systems" address ? */
|
||||
if ((ip_addr_cmp(dest, &allsystems)) && (igmp->igmp_group_address.addr == 0)) {
|
||||
if ((ip_addr_cmp(dest, &allsystems)) && ip_addr_isany(&igmp->igmp_group_address)) {
|
||||
/* THIS IS THE GENERAL QUERY */
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: General IGMP_MEMB_QUERY on \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp)));
|
||||
|
||||
if (igmp->igmp_maxresp == 0) {
|
||||
IGMP_STATS_INC(igmp.v1_rxed);
|
||||
IGMP_STATS_INC(igmp.rx_v1);
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: got an all hosts query with time== 0 - this is V1 and not implemented - treat as v2\n"));
|
||||
igmp->igmp_maxresp = IGMP_V1_DELAYING_MEMBER_TMR;
|
||||
} else {
|
||||
IGMP_STATS_INC(igmp.rx_general);
|
||||
}
|
||||
|
||||
IGMP_STATS_INC(igmp.group_query_rxed);
|
||||
groupref = igmp_group_list;
|
||||
while (groupref) {
|
||||
/* Do not send messages on the all systems group address! */
|
||||
if ((groupref->interface == inp) && (!(ip_addr_cmp(&(groupref->group_address), &allsystems)))) {
|
||||
igmp_delaying_member( groupref, igmp->igmp_maxresp);
|
||||
if ((groupref->netif == inp) && (!(ip_addr_cmp(&(groupref->group_address), &allsystems)))) {
|
||||
igmp_delaying_member(groupref, igmp->igmp_maxresp);
|
||||
}
|
||||
groupref = groupref->next;
|
||||
}
|
||||
} else {
|
||||
/* IGMP_MEMB_QUERY to a specific group ? */
|
||||
if (group->group_address.addr != 0) {
|
||||
if (!ip_addr_isany(&igmp->igmp_group_address)) {
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_MEMB_QUERY to a specific group "));
|
||||
ip_addr_debug_print(IGMP_DEBUG, &group->group_address);
|
||||
if (ip_addr_cmp (dest, &allsystems)) {
|
||||
ip_addr_debug_print(IGMP_DEBUG, &igmp->igmp_group_address);
|
||||
if (ip_addr_cmp(dest, &allsystems)) {
|
||||
ip_addr_t groupaddr;
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (" using \"ALL SYSTEMS\" address (224.0.0.1) [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp)));
|
||||
/* we first need to re-lookfor the group since we used dest last time */
|
||||
group = igmp_lookfor_group(inp, &igmp->igmp_group_address);
|
||||
/* we first need to re-look for the group since we used dest last time */
|
||||
ip_addr_copy(groupaddr, igmp->igmp_group_address);
|
||||
group = igmp_lookfor_group(inp, &groupaddr);
|
||||
} else {
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (" with the group address as destination [igmp_maxresp=%i]\n", (int)(igmp->igmp_maxresp)));
|
||||
}
|
||||
|
||||
if (group != NULL) {
|
||||
IGMP_STATS_INC(igmp.unicast_query);
|
||||
igmp_delaying_member( group, igmp->igmp_maxresp);
|
||||
IGMP_STATS_INC(igmp.rx_group);
|
||||
igmp_delaying_member(group, igmp->igmp_maxresp);
|
||||
} else {
|
||||
IGMP_STATS_INC(igmp.drop);
|
||||
}
|
||||
} else {
|
||||
IGMP_STATS_INC(igmp.proterr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IGMP_V2_MEMB_REPORT: {
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: IGMP_V2_MEMB_REPORT\n"));
|
||||
|
||||
IGMP_STATS_INC(igmp.report_rxed);
|
||||
IGMP_STATS_INC(igmp.rx_report);
|
||||
if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) {
|
||||
/* This is on a specific group we have already looked up */
|
||||
group->timer = 0; /* stopped */
|
||||
@@ -440,7 +494,8 @@ igmp_input(struct pbuf *p, struct netif *inp, struct ip_addr *dest)
|
||||
}
|
||||
default: {
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_input: unexpected msg %d in state %d on group %p on if %p\n",
|
||||
igmp->igmp_msgtype, group->group_state, &group, group->interface));
|
||||
igmp->igmp_msgtype, group->group_state, &group, group->netif));
|
||||
IGMP_STATS_INC(igmp.proterr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -457,7 +512,7 @@ igmp_input(struct pbuf *p, struct netif *inp, struct ip_addr *dest)
|
||||
* @return ERR_OK if group was joined on the netif(s), an err_t otherwise
|
||||
*/
|
||||
err_t
|
||||
igmp_joingroup(struct ip_addr *ifaddr, struct ip_addr *groupaddr)
|
||||
igmp_joingroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr)
|
||||
{
|
||||
err_t err = ERR_VAL; /* no matching interface */
|
||||
struct igmp_group *group;
|
||||
@@ -493,7 +548,7 @@ igmp_joingroup(struct ip_addr *ifaddr, struct ip_addr *groupaddr)
|
||||
netif->igmp_mac_filter(netif, groupaddr, IGMP_ADD_MAC_FILTER);
|
||||
}
|
||||
|
||||
IGMP_STATS_INC(igmp.join_sent);
|
||||
IGMP_STATS_INC(igmp.tx_join);
|
||||
igmp_send(group, IGMP_V2_MEMB_REPORT);
|
||||
|
||||
igmp_start_timer(group, IGMP_JOIN_DELAYING_MEMBER_TMR);
|
||||
@@ -527,7 +582,7 @@ igmp_joingroup(struct ip_addr *ifaddr, struct ip_addr *groupaddr)
|
||||
* @return ERR_OK if group was left on the netif(s), an err_t otherwise
|
||||
*/
|
||||
err_t
|
||||
igmp_leavegroup(struct ip_addr *ifaddr, struct ip_addr *groupaddr)
|
||||
igmp_leavegroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr)
|
||||
{
|
||||
err_t err = ERR_VAL; /* no matching interface */
|
||||
struct igmp_group *group;
|
||||
@@ -556,7 +611,7 @@ igmp_leavegroup(struct ip_addr *ifaddr, struct ip_addr *groupaddr)
|
||||
/* If we are the last reporter for this group */
|
||||
if (group->last_reporter_flag) {
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_leavegroup: sending leaving group\n"));
|
||||
IGMP_STATS_INC(igmp.leave_sent);
|
||||
IGMP_STATS_INC(igmp.tx_leave);
|
||||
igmp_send(group, IGMP_LEAVE_GROUP);
|
||||
}
|
||||
|
||||
@@ -602,8 +657,8 @@ igmp_tmr(void)
|
||||
struct igmp_group *group = igmp_group_list;
|
||||
|
||||
while (group != NULL) {
|
||||
if (group->timer != 0) {
|
||||
group->timer -= 1;
|
||||
if (group->timer > 0) {
|
||||
group->timer--;
|
||||
if (group->timer == 0) {
|
||||
igmp_timeout(group);
|
||||
}
|
||||
@@ -618,15 +673,16 @@ igmp_tmr(void)
|
||||
*
|
||||
* @param group an igmp_group for which a timeout is reached
|
||||
*/
|
||||
void
|
||||
static void
|
||||
igmp_timeout(struct igmp_group *group)
|
||||
{
|
||||
/* If the state is IGMP_GROUP_DELAYING_MEMBER then we send a report for this group */
|
||||
if (group->group_state == IGMP_GROUP_DELAYING_MEMBER) {
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_timeout: report membership for group with address "));
|
||||
ip_addr_debug_print(IGMP_DEBUG, &(group->group_address));
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->interface));
|
||||
LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", group->netif));
|
||||
|
||||
IGMP_STATS_INC(igmp.tx_report);
|
||||
igmp_send(group, IGMP_V2_MEMB_REPORT);
|
||||
}
|
||||
}
|
||||
@@ -638,24 +694,15 @@ igmp_timeout(struct igmp_group *group)
|
||||
* @param max_time the time in multiples of IGMP_TMR_INTERVAL (decrease with
|
||||
* every call to igmp_tmr())
|
||||
*/
|
||||
void
|
||||
static void
|
||||
igmp_start_timer(struct igmp_group *group, u8_t max_time)
|
||||
{
|
||||
/**
|
||||
* @todo Important !! this should be random 0 -> max_time. Find out how to do this
|
||||
*/
|
||||
group->timer = max_time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop a timer for an igmp_group
|
||||
*
|
||||
* @param group the igmp_group for which to stop the timer
|
||||
*/
|
||||
void
|
||||
igmp_stop_timer(struct igmp_group *group)
|
||||
{
|
||||
group->timer = 0;
|
||||
/* ensure the input value is > 0 */
|
||||
if (max_time == 0) {
|
||||
max_time = 1;
|
||||
}
|
||||
/* ensure the random value is > 0 */
|
||||
group->timer = (LWIP_RAND() % (max_time - 1)) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -664,12 +711,13 @@ igmp_stop_timer(struct igmp_group *group)
|
||||
* @param group the igmp_group for which "delaying" membership report
|
||||
* @param maxresp query delay
|
||||
*/
|
||||
void
|
||||
igmp_delaying_member( struct igmp_group *group, u8_t maxresp)
|
||||
static void
|
||||
igmp_delaying_member(struct igmp_group *group, u8_t maxresp)
|
||||
{
|
||||
if ((group->group_state == IGMP_GROUP_IDLE_MEMBER) ||
|
||||
((group->group_state == IGMP_GROUP_DELAYING_MEMBER) && (maxresp > group->timer))) {
|
||||
igmp_start_timer(group, (maxresp)/2);
|
||||
((group->group_state == IGMP_GROUP_DELAYING_MEMBER) &&
|
||||
((group->timer == 0) || (maxresp < group->timer)))) {
|
||||
igmp_start_timer(group, maxresp);
|
||||
group->group_state = IGMP_GROUP_DELAYING_MEMBER;
|
||||
}
|
||||
}
|
||||
@@ -693,15 +741,15 @@ igmp_delaying_member( struct igmp_group *group, u8_t maxresp)
|
||||
* ERR_BUF if p doesn't have enough space for IP/LINK headers
|
||||
* returns errors returned by netif->output
|
||||
*/
|
||||
err_t
|
||||
igmp_ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t ttl, u8_t proto, struct netif *netif)
|
||||
static err_t
|
||||
igmp_ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, struct netif *netif)
|
||||
{
|
||||
/* This is the "router alert" option */
|
||||
u16_t ra[2];
|
||||
ra[0] = htons (ROUTER_ALERT);
|
||||
ra[0] = PP_HTONS(ROUTER_ALERT);
|
||||
ra[1] = 0x0000; /* Router shall examine packet */
|
||||
return ip_output_if_opt(p, src, dest, ttl, 0, proto, netif, ra, ROUTER_ALERTLEN);
|
||||
IGMP_STATS_INC(igmp.xmit);
|
||||
return ip_output_if_opt(p, src, dest, IGMP_TTL, 0, IP_PROTO_IGMP, netif, ra, ROUTER_ALERTLEN);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -710,32 +758,31 @@ igmp_ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
* @param group the group to which to send the packet
|
||||
* @param type the type of igmp packet to send
|
||||
*/
|
||||
void
|
||||
static void
|
||||
igmp_send(struct igmp_group *group, u8_t type)
|
||||
{
|
||||
struct pbuf* p = NULL;
|
||||
struct igmp_msg* igmp = NULL;
|
||||
struct ip_addr src = {0};
|
||||
struct ip_addr* dest = NULL;
|
||||
ip_addr_t src = *IP_ADDR_ANY;
|
||||
ip_addr_t* dest = NULL;
|
||||
|
||||
/* IP header + "router alert" option + IGMP header */
|
||||
p = pbuf_alloc(PBUF_TRANSPORT, IGMP_MINLEN, PBUF_RAM);
|
||||
|
||||
if (p) {
|
||||
igmp = p->payload;
|
||||
igmp = (struct igmp_msg *)p->payload;
|
||||
LWIP_ASSERT("igmp_send: check that first pbuf can hold struct igmp_msg",
|
||||
(p->len >= sizeof(struct igmp_msg)));
|
||||
ip_addr_set(&src, &((group->interface)->ip_addr));
|
||||
ip_addr_copy(src, group->netif->ip_addr);
|
||||
|
||||
if (type == IGMP_V2_MEMB_REPORT) {
|
||||
dest = &(group->group_address);
|
||||
IGMP_STATS_INC(igmp.report_sent);
|
||||
ip_addr_set(&(igmp->igmp_group_address), &(group->group_address));
|
||||
ip_addr_copy(igmp->igmp_group_address, group->group_address);
|
||||
group->last_reporter_flag = 1; /* Remember we were the last to report */
|
||||
} else {
|
||||
if (type == IGMP_LEAVE_GROUP) {
|
||||
dest = &allrouters;
|
||||
ip_addr_set(&(igmp->igmp_group_address), &(group->group_address));
|
||||
ip_addr_copy(igmp->igmp_group_address, group->group_address);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -743,14 +790,15 @@ igmp_send(struct igmp_group *group, u8_t type)
|
||||
igmp->igmp_msgtype = type;
|
||||
igmp->igmp_maxresp = 0;
|
||||
igmp->igmp_checksum = 0;
|
||||
igmp->igmp_checksum = inet_chksum( igmp, IGMP_MINLEN);
|
||||
igmp->igmp_checksum = inet_chksum(igmp, IGMP_MINLEN);
|
||||
|
||||
igmp_ip_output_if(p, &src, dest, IGMP_TTL, IP_PROTO_IGMP, group->interface);
|
||||
igmp_ip_output_if(p, &src, dest, group->netif);
|
||||
}
|
||||
|
||||
pbuf_free(p);
|
||||
} else {
|
||||
LWIP_DEBUGF(IGMP_DEBUG, ("igmp_send: not enough memory for igmp_send\n"));
|
||||
IGMP_STATS_INC(igmp.memerr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,239 +40,3 @@
|
||||
|
||||
#include "lwip/inet.h"
|
||||
|
||||
/* Here for now until needed in other places in lwIP */
|
||||
#ifndef isprint
|
||||
#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up)
|
||||
#define isprint(c) in_range(c, 0x20, 0x7f)
|
||||
#define isdigit(c) in_range(c, '0', '9')
|
||||
#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
|
||||
#define islower(c) in_range(c, 'a', 'z')
|
||||
#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Ascii internet address interpretation routine.
|
||||
* The value returned is in network order.
|
||||
*
|
||||
* @param cp IP address in ascii represenation (e.g. "127.0.0.1")
|
||||
* @return ip address in network order
|
||||
*/
|
||||
u32_t
|
||||
inet_addr(const char *cp)
|
||||
{
|
||||
struct in_addr val;
|
||||
|
||||
if (inet_aton(cp, &val)) {
|
||||
return (val.s_addr);
|
||||
}
|
||||
return (INADDR_NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether "cp" is a valid ascii representation
|
||||
* of an Internet address and convert to a binary address.
|
||||
* Returns 1 if the address is valid, 0 if not.
|
||||
* This replaces inet_addr, the return value from which
|
||||
* cannot distinguish between failure and a local broadcast address.
|
||||
*
|
||||
* @param cp IP address in ascii represenation (e.g. "127.0.0.1")
|
||||
* @param addr pointer to which to save the ip address in network order
|
||||
* @return 1 if cp could be converted to addr, 0 on failure
|
||||
*/
|
||||
int
|
||||
inet_aton(const char *cp, struct in_addr *addr)
|
||||
{
|
||||
u32_t val;
|
||||
u8_t base;
|
||||
char c;
|
||||
u32_t parts[4];
|
||||
u32_t *pp = parts;
|
||||
|
||||
c = *cp;
|
||||
for (;;) {
|
||||
/*
|
||||
* Collect number up to ``.''.
|
||||
* Values are specified as for C:
|
||||
* 0x=hex, 0=octal, 1-9=decimal.
|
||||
*/
|
||||
if (!isdigit(c))
|
||||
return (0);
|
||||
val = 0;
|
||||
base = 10;
|
||||
if (c == '0') {
|
||||
c = *++cp;
|
||||
if (c == 'x' || c == 'X') {
|
||||
base = 16;
|
||||
c = *++cp;
|
||||
} else
|
||||
base = 8;
|
||||
}
|
||||
for (;;) {
|
||||
if (isdigit(c)) {
|
||||
val = (val * base) + (int)(c - '0');
|
||||
c = *++cp;
|
||||
} else if (base == 16 && isxdigit(c)) {
|
||||
val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A'));
|
||||
c = *++cp;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
if (c == '.') {
|
||||
/*
|
||||
* Internet format:
|
||||
* a.b.c.d
|
||||
* a.b.c (with c treated as 16 bits)
|
||||
* a.b (with b treated as 24 bits)
|
||||
*/
|
||||
if (pp >= parts + 3)
|
||||
return (0);
|
||||
*pp++ = val;
|
||||
c = *++cp;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Check for trailing characters.
|
||||
*/
|
||||
if (c != '\0' && !isspace(c))
|
||||
return (0);
|
||||
/*
|
||||
* Concoct the address according to
|
||||
* the number of parts specified.
|
||||
*/
|
||||
switch (pp - parts + 1) {
|
||||
|
||||
case 0:
|
||||
return (0); /* initial nondigit */
|
||||
|
||||
case 1: /* a -- 32 bits */
|
||||
break;
|
||||
|
||||
case 2: /* a.b -- 8.24 bits */
|
||||
if (val > 0xffffffUL)
|
||||
return (0);
|
||||
val |= parts[0] << 24;
|
||||
break;
|
||||
|
||||
case 3: /* a.b.c -- 8.8.16 bits */
|
||||
if (val > 0xffff)
|
||||
return (0);
|
||||
val |= (parts[0] << 24) | (parts[1] << 16);
|
||||
break;
|
||||
|
||||
case 4: /* a.b.c.d -- 8.8.8.8 bits */
|
||||
if (val > 0xff)
|
||||
return (0);
|
||||
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
|
||||
break;
|
||||
}
|
||||
if (addr)
|
||||
addr->s_addr = htonl(val);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert numeric IP address into decimal dotted ASCII representation.
|
||||
* returns ptr to static buffer; not reentrant!
|
||||
*
|
||||
* @param addr ip address in network order to convert
|
||||
* @return pointer to a global static (!) buffer that holds the ASCII
|
||||
* represenation of addr
|
||||
*/
|
||||
char *
|
||||
inet_ntoa(struct in_addr addr)
|
||||
{
|
||||
static char str[16];
|
||||
u32_t s_addr = addr.s_addr;
|
||||
char inv[3];
|
||||
char *rp;
|
||||
u8_t *ap;
|
||||
u8_t rem;
|
||||
u8_t n;
|
||||
u8_t i;
|
||||
|
||||
rp = str;
|
||||
ap = (u8_t *)&s_addr;
|
||||
for(n = 0; n < 4; n++) {
|
||||
i = 0;
|
||||
do {
|
||||
rem = *ap % (u8_t)10;
|
||||
*ap /= (u8_t)10;
|
||||
inv[i++] = '0' + rem;
|
||||
} while(*ap);
|
||||
while(i--)
|
||||
*rp++ = inv[i];
|
||||
*rp++ = '.';
|
||||
ap++;
|
||||
}
|
||||
*--rp = 0;
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* These are reference implementations of the byte swapping functions.
|
||||
* Again with the aim of being simple, correct and fully portable.
|
||||
* Byte swapping is the second thing you would want to optimize. You will
|
||||
* need to port it to your architecture and in your cc.h:
|
||||
*
|
||||
* #define LWIP_PLATFORM_BYTESWAP 1
|
||||
* #define LWIP_PLATFORM_HTONS(x) <your_htons>
|
||||
* #define LWIP_PLATFORM_HTONL(x) <your_htonl>
|
||||
*
|
||||
* Note ntohs() and ntohl() are merely references to the htonx counterparts.
|
||||
*/
|
||||
|
||||
#if (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
|
||||
/**
|
||||
* Convert an u16_t from host- to network byte order.
|
||||
*
|
||||
* @param n u16_t in host byte order
|
||||
* @return n in network byte order
|
||||
*/
|
||||
u16_t
|
||||
htons(u16_t n)
|
||||
{
|
||||
return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an u16_t from network- to host byte order.
|
||||
*
|
||||
* @param n u16_t in network byte order
|
||||
* @return n in host byte order
|
||||
*/
|
||||
u16_t
|
||||
ntohs(u16_t n)
|
||||
{
|
||||
return htons(n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an u32_t from host- to network byte order.
|
||||
*
|
||||
* @param n u32_t in host byte order
|
||||
* @return n in network byte order
|
||||
*/
|
||||
u32_t
|
||||
htonl(u32_t n)
|
||||
{
|
||||
return ((n & 0xff) << 24) |
|
||||
((n & 0xff00) << 8) |
|
||||
((n & 0xff0000UL) >> 8) |
|
||||
((n & 0xff000000UL) >> 24);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an u32_t from network- to host byte order.
|
||||
*
|
||||
* @param n u32_t in network byte order
|
||||
* @return n in host byte order
|
||||
*/
|
||||
u32_t
|
||||
ntohl(u32_t n)
|
||||
{
|
||||
return htonl(n);
|
||||
}
|
||||
|
||||
#endif /* (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) */
|
||||
|
||||
@@ -39,9 +39,10 @@
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/def.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
/* These are some reference implementations of the checksum algorithm, with the
|
||||
* aim of being simple, correct and fully portable. Checksumming is the
|
||||
@@ -57,7 +58,7 @@
|
||||
#ifndef LWIP_CHKSUM
|
||||
# define LWIP_CHKSUM lwip_standard_chksum
|
||||
# ifndef LWIP_CHKSUM_ALGORITHM
|
||||
# define LWIP_CHKSUM_ALGORITHM 1
|
||||
# define LWIP_CHKSUM_ALGORITHM 2
|
||||
# endif
|
||||
#endif
|
||||
/* If none set: */
|
||||
@@ -65,18 +66,6 @@
|
||||
# define LWIP_CHKSUM_ALGORITHM 0
|
||||
#endif
|
||||
|
||||
/** Like the name says... */
|
||||
#if LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
/* little endian and PLATFORM_BYTESWAP defined */
|
||||
#define SWAP_BYTES_IN_WORD(w) LWIP_PLATFORM_HTONS(w)
|
||||
#else
|
||||
/* can't use htons on big endian (or PLATFORM_BYTESWAP not defined)... */
|
||||
#define SWAP_BYTES_IN_WORD(w) ((w & 0xff) << 8) | ((w & 0xff00) >> 8)
|
||||
#endif
|
||||
|
||||
/** Split an u32_t in two u16_ts and add them up */
|
||||
#define FOLD_U32T(u) ((u >> 16) + (u & 0x0000ffffUL))
|
||||
|
||||
#if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */
|
||||
/**
|
||||
* lwip checksum
|
||||
@@ -145,10 +134,10 @@ lwip_standard_chksum(void *dataptr, u16_t len)
|
||||
static u16_t
|
||||
lwip_standard_chksum(void *dataptr, int len)
|
||||
{
|
||||
u8_t *pb = dataptr;
|
||||
u8_t *pb = (u8_t *)dataptr;
|
||||
u16_t *ps, t = 0;
|
||||
u32_t sum = 0;
|
||||
int odd = ((u32_t)pb & 1);
|
||||
int odd = ((mem_ptr_t)pb & 1);
|
||||
|
||||
/* Get aligned to u16_t */
|
||||
if (odd && len > 0) {
|
||||
@@ -157,7 +146,7 @@ lwip_standard_chksum(void *dataptr, int len)
|
||||
}
|
||||
|
||||
/* Add the bulk of the data */
|
||||
ps = (u16_t *)pb;
|
||||
ps = (u16_t *)(void *)pb;
|
||||
while (len > 1) {
|
||||
sum += *ps++;
|
||||
len -= 2;
|
||||
@@ -165,7 +154,7 @@ lwip_standard_chksum(void *dataptr, int len)
|
||||
|
||||
/* Consume left-over byte, if any */
|
||||
if (len > 0) {
|
||||
((u8_t *)&t)[0] = *(u8_t *)ps;;
|
||||
((u8_t *)&t)[0] = *(u8_t *)ps;
|
||||
}
|
||||
|
||||
/* Add end bytes */
|
||||
@@ -181,7 +170,7 @@ lwip_standard_chksum(void *dataptr, int len)
|
||||
sum = SWAP_BYTES_IN_WORD(sum);
|
||||
}
|
||||
|
||||
return sum;
|
||||
return (u16_t)sum;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -201,12 +190,12 @@ lwip_standard_chksum(void *dataptr, int len)
|
||||
static u16_t
|
||||
lwip_standard_chksum(void *dataptr, int len)
|
||||
{
|
||||
u8_t *pb = dataptr;
|
||||
u8_t *pb = (u8_t *)dataptr;
|
||||
u16_t *ps, t = 0;
|
||||
u32_t *pl;
|
||||
u32_t sum = 0, tmp;
|
||||
/* starts at odd byte address? */
|
||||
int odd = ((u32_t)pb & 1);
|
||||
int odd = ((mem_ptr_t)pb & 1);
|
||||
|
||||
if (odd && len > 0) {
|
||||
((u8_t *)&t)[1] = *pb++;
|
||||
@@ -215,7 +204,7 @@ lwip_standard_chksum(void *dataptr, int len)
|
||||
|
||||
ps = (u16_t *)pb;
|
||||
|
||||
if (((u32_t)ps & 3) && len > 1) {
|
||||
if (((mem_ptr_t)ps & 3) && len > 1) {
|
||||
sum += *ps++;
|
||||
len -= 2;
|
||||
}
|
||||
@@ -263,7 +252,7 @@ lwip_standard_chksum(void *dataptr, int len)
|
||||
sum = SWAP_BYTES_IN_WORD(sum);
|
||||
}
|
||||
|
||||
return sum;
|
||||
return (u16_t)sum;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -281,10 +270,11 @@ lwip_standard_chksum(void *dataptr, int len)
|
||||
*/
|
||||
u16_t
|
||||
inet_chksum_pseudo(struct pbuf *p,
|
||||
struct ip_addr *src, struct ip_addr *dest,
|
||||
ip_addr_t *src, ip_addr_t *dest,
|
||||
u8_t proto, u16_t proto_len)
|
||||
{
|
||||
u32_t acc;
|
||||
u32_t addr;
|
||||
struct pbuf *q;
|
||||
u8_t swapped;
|
||||
|
||||
@@ -309,10 +299,12 @@ inet_chksum_pseudo(struct pbuf *p,
|
||||
if (swapped) {
|
||||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
acc += (src->addr & 0xffffUL);
|
||||
acc += ((src->addr >> 16) & 0xffffUL);
|
||||
acc += (dest->addr & 0xffffUL);
|
||||
acc += ((dest->addr >> 16) & 0xffffUL);
|
||||
addr = ip4_addr_get_u32(src);
|
||||
acc += (addr & 0xffffUL);
|
||||
acc += ((addr >> 16) & 0xffffUL);
|
||||
addr = ip4_addr_get_u32(dest);
|
||||
acc += (addr & 0xffffUL);
|
||||
acc += ((addr >> 16) & 0xffffUL);
|
||||
acc += (u32_t)htons((u16_t)proto);
|
||||
acc += (u32_t)htons(proto_len);
|
||||
|
||||
@@ -336,14 +328,13 @@ inet_chksum_pseudo(struct pbuf *p,
|
||||
* @param proto_len length of the ip data part (used for checksum of pseudo header)
|
||||
* @return checksum (as u16_t) to be saved directly in the protocol header
|
||||
*/
|
||||
/* Currently only used by UDPLITE, although this could change in the future. */
|
||||
#if LWIP_UDPLITE
|
||||
u16_t
|
||||
inet_chksum_pseudo_partial(struct pbuf *p,
|
||||
struct ip_addr *src, struct ip_addr *dest,
|
||||
ip_addr_t *src, ip_addr_t *dest,
|
||||
u8_t proto, u16_t proto_len, u16_t chksum_len)
|
||||
{
|
||||
u32_t acc;
|
||||
u32_t addr;
|
||||
struct pbuf *q;
|
||||
u8_t swapped;
|
||||
u16_t chklen;
|
||||
@@ -374,10 +365,12 @@ inet_chksum_pseudo_partial(struct pbuf *p,
|
||||
if (swapped) {
|
||||
acc = SWAP_BYTES_IN_WORD(acc);
|
||||
}
|
||||
acc += (src->addr & 0xffffUL);
|
||||
acc += ((src->addr >> 16) & 0xffffUL);
|
||||
acc += (dest->addr & 0xffffUL);
|
||||
acc += ((dest->addr >> 16) & 0xffffUL);
|
||||
addr = ip4_addr_get_u32(src);
|
||||
acc += (addr & 0xffffUL);
|
||||
acc += ((addr >> 16) & 0xffffUL);
|
||||
addr = ip4_addr_get_u32(dest);
|
||||
acc += (addr & 0xffffUL);
|
||||
acc += ((addr >> 16) & 0xffffUL);
|
||||
acc += (u32_t)htons((u16_t)proto);
|
||||
acc += (u32_t)htons(proto_len);
|
||||
|
||||
@@ -388,7 +381,6 @@ inet_chksum_pseudo_partial(struct pbuf *p,
|
||||
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
|
||||
return (u16_t)~(acc & 0xffffUL);
|
||||
}
|
||||
#endif /* LWIP_UDPLITE */
|
||||
|
||||
/* inet_chksum:
|
||||
*
|
||||
@@ -436,3 +428,23 @@ inet_chksum_pbuf(struct pbuf *p)
|
||||
}
|
||||
return (u16_t)~(acc & 0xffffUL);
|
||||
}
|
||||
|
||||
/* These are some implementations for LWIP_CHKSUM_COPY, which copies data
|
||||
* like MEMCPY but generates a checksum at the same time. Since this is a
|
||||
* performance-sensitive function, you might want to create your own version
|
||||
* in assembly targeted at your hardware by defining it in lwipopts.h:
|
||||
* #define LWIP_CHKSUM_COPY(dst, src, len) your_chksum_copy(dst, src, len)
|
||||
*/
|
||||
|
||||
#if (LWIP_CHKSUM_COPY_ALGORITHM == 1) /* Version #1 */
|
||||
/** Safe but slow: first call MEMCPY, then call LWIP_CHKSUM.
|
||||
* For architectures with big caches, data might still be in cache when
|
||||
* generating the checksum after copying.
|
||||
*/
|
||||
u16_t
|
||||
lwip_chksum_copy(void *dst, const void *src, u16_t len)
|
||||
{
|
||||
MEMCPY(dst, src, len);
|
||||
return LWIP_CHKSUM(dst, len);
|
||||
}
|
||||
#endif /* (LWIP_CHKSUM_COPY_ALGORITHM == 1) */
|
||||
|
||||
@@ -43,21 +43,56 @@
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/ip_frag.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/icmp.h"
|
||||
#include "lwip/igmp.h"
|
||||
#include "lwip/raw.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/tcp_impl.h"
|
||||
#include "lwip/snmp.h"
|
||||
#include "lwip/dhcp.h"
|
||||
#include "lwip/autoip.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "arch/perf.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/** Set this to 0 in the rare case of wanting to call an extra function to
|
||||
* generate the IP checksum (in contrast to calculating it on-the-fly). */
|
||||
#ifndef LWIP_INLINE_IP_CHKSUM
|
||||
#define LWIP_INLINE_IP_CHKSUM 1
|
||||
#endif
|
||||
#if LWIP_INLINE_IP_CHKSUM && CHECKSUM_GEN_IP
|
||||
#define CHECKSUM_GEN_IP_INLINE 1
|
||||
#else
|
||||
#define CHECKSUM_GEN_IP_INLINE 0
|
||||
#endif
|
||||
|
||||
#if LWIP_DHCP || defined(LWIP_IP_ACCEPT_UDP_PORT)
|
||||
#define IP_ACCEPT_LINK_LAYER_ADDRESSING 1
|
||||
|
||||
/** Some defines for DHCP to let link-layer-addressed packets through while the
|
||||
* netif is down.
|
||||
* To use this in your own application/protocol, define LWIP_IP_ACCEPT_UDP_PORT
|
||||
* to return 1 if the port is accepted and 0 if the port is not accepted.
|
||||
*/
|
||||
#if LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT)
|
||||
/* accept DHCP client port and custom port */
|
||||
#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (((port) == PP_NTOHS(DHCP_CLIENT_PORT)) \
|
||||
|| (LWIP_IP_ACCEPT_UDP_PORT(port)))
|
||||
#elif defined(LWIP_IP_ACCEPT_UDP_PORT) /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */
|
||||
/* accept custom port only */
|
||||
#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (LWIP_IP_ACCEPT_UDP_PORT(port))
|
||||
#else /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */
|
||||
/* accept DHCP client port only */
|
||||
#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) ((port) == PP_NTOHS(DHCP_CLIENT_PORT))
|
||||
#endif /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */
|
||||
|
||||
#else /* LWIP_DHCP */
|
||||
#define IP_ACCEPT_LINK_LAYER_ADDRESSING 0
|
||||
#endif /* LWIP_DHCP */
|
||||
|
||||
/**
|
||||
* The interface that provided the packet for the current callback
|
||||
* invocation.
|
||||
@@ -68,6 +103,13 @@ struct netif *current_netif;
|
||||
* Header of the input packet currently being processed.
|
||||
*/
|
||||
const struct ip_hdr *current_header;
|
||||
/** Source IP address of current_header */
|
||||
ip_addr_t current_iphdr_src;
|
||||
/** Destination IP address of current_header */
|
||||
ip_addr_t current_iphdr_dest;
|
||||
|
||||
/** The IP header ID of the next outgoing IP packet */
|
||||
static u16_t ip_id;
|
||||
|
||||
/**
|
||||
* Finds the appropriate network interface for a given IP address. It
|
||||
@@ -79,12 +121,19 @@ const struct ip_hdr *current_header;
|
||||
* @return the netif on which to send to reach dest
|
||||
*/
|
||||
struct netif *
|
||||
ip_route(struct ip_addr *dest)
|
||||
ip_route(ip_addr_t *dest)
|
||||
{
|
||||
struct netif *netif;
|
||||
|
||||
#ifdef LWIP_HOOK_IP4_ROUTE
|
||||
netif = LWIP_HOOK_IP4_ROUTE(dest);
|
||||
if (netif != NULL) {
|
||||
return netif;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* iterate through netifs */
|
||||
for(netif = netif_list; netif != NULL; netif = netif->next) {
|
||||
for (netif = netif_list; netif != NULL; netif = netif->next) {
|
||||
/* network mask matches? */
|
||||
if (netif_is_up(netif)) {
|
||||
if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
|
||||
@@ -94,7 +143,8 @@ ip_route(struct ip_addr *dest)
|
||||
}
|
||||
}
|
||||
if ((netif_default == NULL) || (!netif_is_up(netif_default))) {
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_route: No route to 0x%"X32_F"\n", dest->addr));
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));
|
||||
IP_STATS_INC(ip.rterr);
|
||||
snmp_inc_ipoutnoroutes();
|
||||
return NULL;
|
||||
@@ -104,6 +154,41 @@ ip_route(struct ip_addr *dest)
|
||||
}
|
||||
|
||||
#if IP_FORWARD
|
||||
/**
|
||||
* Determine whether an IP address is in a reserved set of addresses
|
||||
* that may not be forwarded, or whether datagrams to that destination
|
||||
* may be forwarded.
|
||||
* @param p the packet to forward
|
||||
* @param dest the destination IP address
|
||||
* @return 1: can forward 0: discard
|
||||
*/
|
||||
static int
|
||||
ip_canforward(struct pbuf *p)
|
||||
{
|
||||
u32_t addr = ip4_addr_get_u32(ip_current_dest_addr());
|
||||
|
||||
if (p->flags & PBUF_FLAG_LLBCAST) {
|
||||
/* don't route link-layer broadcasts */
|
||||
return 0;
|
||||
}
|
||||
if ((p->flags & PBUF_FLAG_LLMCAST) && !IP_MULTICAST(addr)) {
|
||||
/* don't route link-layer multicasts unless the destination address is an IP
|
||||
multicast address */
|
||||
return 0;
|
||||
}
|
||||
if (IP_EXPERIMENTAL(addr)) {
|
||||
return 0;
|
||||
}
|
||||
if (IP_CLASSA(addr)) {
|
||||
u32_t net = addr & IP_CLASSA_NET;
|
||||
if ((net == 0) || (net == (IP_LOOPBACKNET << IP_CLASSA_NSHIFT))) {
|
||||
/* don't route loopback packets */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards an IP packet. It finds an appropriate route for the
|
||||
* packet, decrements the TTL value of the packet, adjusts the
|
||||
@@ -112,29 +197,43 @@ ip_route(struct ip_addr *dest)
|
||||
* @param p the packet to forward (p->payload points to IP header)
|
||||
* @param iphdr the IP header of the input packet
|
||||
* @param inp the netif on which this packet was received
|
||||
* @return the netif on which the packet was sent (NULL if it wasn't sent)
|
||||
*/
|
||||
static struct netif *
|
||||
static void
|
||||
ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
|
||||
{
|
||||
struct netif *netif;
|
||||
|
||||
PERF_START;
|
||||
/* Find network interface where to forward this IP packet to. */
|
||||
netif = ip_route((struct ip_addr *)&(iphdr->dest));
|
||||
if (netif == NULL) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for 0x%"X32_F" found\n",
|
||||
iphdr->dest.addr));
|
||||
snmp_inc_ipoutnoroutes();
|
||||
return (struct netif *)NULL;
|
||||
|
||||
if (!ip_canforward(p)) {
|
||||
goto return_noroute;
|
||||
}
|
||||
|
||||
/* RFC3927 2.7: do not forward link-local addresses */
|
||||
if (ip_addr_islinklocal(¤t_iphdr_dest)) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
ip4_addr1_16(¤t_iphdr_dest), ip4_addr2_16(¤t_iphdr_dest),
|
||||
ip4_addr3_16(¤t_iphdr_dest), ip4_addr4_16(¤t_iphdr_dest)));
|
||||
goto return_noroute;
|
||||
}
|
||||
|
||||
/* Find network interface where to forward this IP packet to. */
|
||||
netif = ip_route(¤t_iphdr_dest);
|
||||
if (netif == NULL) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for %"U16_F".%"U16_F".%"U16_F".%"U16_F" found\n",
|
||||
ip4_addr1_16(¤t_iphdr_dest), ip4_addr2_16(¤t_iphdr_dest),
|
||||
ip4_addr3_16(¤t_iphdr_dest), ip4_addr4_16(¤t_iphdr_dest)));
|
||||
/* @todo: send ICMP_DUR_NET? */
|
||||
goto return_noroute;
|
||||
}
|
||||
#if !IP_FORWARD_ALLOW_TX_ON_RX_NETIF
|
||||
/* Do not forward packets onto the same network interface on which
|
||||
* they arrived. */
|
||||
if (netif == inp) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n"));
|
||||
snmp_inc_ipoutnoroutes();
|
||||
return (struct netif *)NULL;
|
||||
goto return_noroute;
|
||||
}
|
||||
#endif /* IP_FORWARD_ALLOW_TX_ON_RX_NETIF */
|
||||
|
||||
/* decrement TTL */
|
||||
IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1);
|
||||
@@ -147,27 +246,44 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
|
||||
icmp_time_exceeded(p, ICMP_TE_TTL);
|
||||
}
|
||||
#endif /* LWIP_ICMP */
|
||||
return (struct netif *)NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Incrementally update the IP checksum. */
|
||||
if (IPH_CHKSUM(iphdr) >= htons(0xffff - 0x100)) {
|
||||
IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100) + 1);
|
||||
if (IPH_CHKSUM(iphdr) >= PP_HTONS(0xffffU - 0x100)) {
|
||||
IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100) + 1);
|
||||
} else {
|
||||
IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100));
|
||||
IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100));
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%"X32_F"\n",
|
||||
iphdr->dest.addr));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
ip4_addr1_16(¤t_iphdr_dest), ip4_addr2_16(¤t_iphdr_dest),
|
||||
ip4_addr3_16(¤t_iphdr_dest), ip4_addr4_16(¤t_iphdr_dest)));
|
||||
|
||||
IP_STATS_INC(ip.fw);
|
||||
IP_STATS_INC(ip.xmit);
|
||||
snmp_inc_ipforwdatagrams();
|
||||
|
||||
PERF_STOP("ip_forward");
|
||||
/* don't fragment if interface has mtu set to 0 [loopif] */
|
||||
if (netif->mtu && (p->tot_len > netif->mtu)) {
|
||||
if ((IPH_OFFSET(iphdr) & PP_NTOHS(IP_DF)) == 0) {
|
||||
#if IP_FRAG
|
||||
ip_frag(p, netif, ip_current_dest_addr());
|
||||
#else /* IP_FRAG */
|
||||
/* @todo: send ICMP Destination Unreacheable code 13 "Communication administratively prohibited"? */
|
||||
#endif /* IP_FRAG */
|
||||
} else {
|
||||
/* send ICMP Destination Unreacheable code 4: "Fragmentation Needed and DF Set" */
|
||||
icmp_dest_unreach(p, ICMP_DUR_FRAG);
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* transmit pbuf on chosen interface */
|
||||
netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
|
||||
return netif;
|
||||
netif->output(netif, p, ¤t_iphdr_dest);
|
||||
return;
|
||||
return_noroute:
|
||||
snmp_inc_ipoutnoroutes();
|
||||
}
|
||||
#endif /* IP_FORWARD */
|
||||
|
||||
@@ -192,15 +308,15 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
struct netif *netif;
|
||||
u16_t iphdr_hlen;
|
||||
u16_t iphdr_len;
|
||||
#if LWIP_DHCP
|
||||
#if IP_ACCEPT_LINK_LAYER_ADDRESSING
|
||||
int check_ip_src=1;
|
||||
#endif /* LWIP_DHCP */
|
||||
#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
|
||||
|
||||
IP_STATS_INC(ip.recv);
|
||||
snmp_inc_ipinreceives();
|
||||
|
||||
/* identify the IP header */
|
||||
iphdr = p->payload;
|
||||
iphdr = (struct ip_hdr *)p->payload;
|
||||
if (IPH_V(iphdr) != 4) {
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_WARNING, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr)));
|
||||
ip_debug_print(p);
|
||||
@@ -211,6 +327,13 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
#ifdef LWIP_HOOK_IP4_INPUT
|
||||
if (LWIP_HOOK_IP4_INPUT(p, inp)) {
|
||||
/* the packet has been eaten */
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* obtain IP header length in number of 32-bit words */
|
||||
iphdr_hlen = IPH_HL(iphdr);
|
||||
/* calculate IP header length in bytes */
|
||||
@@ -257,10 +380,14 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
* but we'll do it anyway just to be sure that its done. */
|
||||
pbuf_realloc(p, iphdr_len);
|
||||
|
||||
/* copy IP addresses to aligned ip_addr_t */
|
||||
ip_addr_copy(current_iphdr_dest, iphdr->dest);
|
||||
ip_addr_copy(current_iphdr_src, iphdr->src);
|
||||
|
||||
/* match packet against an interface, i.e. is this packet for us? */
|
||||
#if LWIP_IGMP
|
||||
if (ip_addr_ismulticast(&(iphdr->dest))) {
|
||||
if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, &(iphdr->dest)))) {
|
||||
if (ip_addr_ismulticast(¤t_iphdr_dest)) {
|
||||
if ((inp->flags & NETIF_FLAG_IGMP) && (igmp_lookfor_group(inp, ¤t_iphdr_dest))) {
|
||||
netif = inp;
|
||||
} else {
|
||||
netif = NULL;
|
||||
@@ -275,22 +402,33 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
netif = inp;
|
||||
do {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n",
|
||||
iphdr->dest.addr, netif->ip_addr.addr,
|
||||
iphdr->dest.addr & netif->netmask.addr,
|
||||
netif->ip_addr.addr & netif->netmask.addr,
|
||||
iphdr->dest.addr & ~(netif->netmask.addr)));
|
||||
ip4_addr_get_u32(&iphdr->dest), ip4_addr_get_u32(&netif->ip_addr),
|
||||
ip4_addr_get_u32(&iphdr->dest) & ip4_addr_get_u32(&netif->netmask),
|
||||
ip4_addr_get_u32(&netif->ip_addr) & ip4_addr_get_u32(&netif->netmask),
|
||||
ip4_addr_get_u32(&iphdr->dest) & ~ip4_addr_get_u32(&netif->netmask)));
|
||||
|
||||
/* interface is up and configured? */
|
||||
if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr)))) {
|
||||
/* unicast to this interface address? */
|
||||
if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
|
||||
if (ip_addr_cmp(¤t_iphdr_dest, &(netif->ip_addr)) ||
|
||||
/* or broadcast on this interface network address? */
|
||||
ip_addr_isbroadcast(&(iphdr->dest), netif)) {
|
||||
ip_addr_isbroadcast(¤t_iphdr_dest, netif)) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
|
||||
netif->name[0], netif->name[1]));
|
||||
/* break out of for loop */
|
||||
break;
|
||||
}
|
||||
#if LWIP_AUTOIP
|
||||
/* connections to link-local addresses must persist after changing
|
||||
the netif's address (RFC3927 ch. 1.9) */
|
||||
if ((netif->autoip != NULL) &&
|
||||
ip_addr_cmp(¤t_iphdr_dest, &(netif->autoip->llipaddr))) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: LLA packet accepted on interface %c%c\n",
|
||||
netif->name[0], netif->name[1]));
|
||||
/* break out of for loop */
|
||||
break;
|
||||
}
|
||||
#endif /* LWIP_AUTOIP */
|
||||
}
|
||||
if (first) {
|
||||
first = 0;
|
||||
@@ -304,32 +442,38 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
} while(netif != NULL);
|
||||
}
|
||||
|
||||
#if LWIP_DHCP
|
||||
#if IP_ACCEPT_LINK_LAYER_ADDRESSING
|
||||
/* Pass DHCP messages regardless of destination address. DHCP traffic is addressed
|
||||
* using link layer addressing (such as Ethernet MAC) so we must not filter on IP.
|
||||
* According to RFC 1542 section 3.1.1, referred by RFC 2131).
|
||||
*
|
||||
* If you want to accept private broadcast communication while a netif is down,
|
||||
* define LWIP_IP_ACCEPT_UDP_PORT(dst_port), e.g.:
|
||||
*
|
||||
* #define LWIP_IP_ACCEPT_UDP_PORT(dst_port) ((dst_port) == PP_NTOHS(12345))
|
||||
*/
|
||||
if (netif == NULL) {
|
||||
/* remote port is DHCP server? */
|
||||
if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
|
||||
struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen);
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: UDP packet to DHCP client port %"U16_F"\n",
|
||||
ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest)));
|
||||
if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen))->dest) == DHCP_CLIENT_PORT) {
|
||||
ntohs(udphdr->dest)));
|
||||
if (IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(udphdr->dest)) {
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: DHCP packet accepted.\n"));
|
||||
netif = inp;
|
||||
check_ip_src = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_DHCP */
|
||||
#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
|
||||
|
||||
/* broadcast or multicast packet source address? Compliant with RFC 1122: 3.2.1.3 */
|
||||
#if LWIP_DHCP
|
||||
#if IP_ACCEPT_LINK_LAYER_ADDRESSING
|
||||
/* DHCP servers need 0.0.0.0 to be allowed as source address (RFC 1.1.2.2: 3.2.1.3/a) */
|
||||
if (check_ip_src && (iphdr->src.addr != 0))
|
||||
#endif /* LWIP_DHCP */
|
||||
{ if ((ip_addr_isbroadcast(&(iphdr->src), inp)) ||
|
||||
(ip_addr_ismulticast(&(iphdr->src)))) {
|
||||
if (check_ip_src && !ip_addr_isany(¤t_iphdr_src))
|
||||
#endif /* IP_ACCEPT_LINK_LAYER_ADDRESSING */
|
||||
{ if ((ip_addr_isbroadcast(¤t_iphdr_src, inp)) ||
|
||||
(ip_addr_ismulticast(¤t_iphdr_src))) {
|
||||
/* packet source is not valid */
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("ip_input: packet source is not valid.\n"));
|
||||
/* free (drop) packet pbufs */
|
||||
@@ -347,7 +491,7 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip_input: packet not for us.\n"));
|
||||
#if IP_FORWARD
|
||||
/* non-broadcast packet? */
|
||||
if (!ip_addr_isbroadcast(&(iphdr->dest), inp)) {
|
||||
if (!ip_addr_isbroadcast(¤t_iphdr_dest, inp)) {
|
||||
/* try to forward IP packet on (other) interfaces */
|
||||
ip_forward(p, iphdr, inp);
|
||||
} else
|
||||
@@ -360,17 +504,17 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
return ERR_OK;
|
||||
}
|
||||
/* packet consists of multiple fragments? */
|
||||
if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
|
||||
if ((IPH_OFFSET(iphdr) & PP_HTONS(IP_OFFMASK | IP_MF)) != 0) {
|
||||
#if IP_REASSEMBLY /* packet fragment reassembly code present? */
|
||||
LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip_reass()\n",
|
||||
ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & htons(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8));
|
||||
ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & PP_HTONS(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8));
|
||||
/* reassemble the packet*/
|
||||
p = ip_reass(p);
|
||||
/* packet not fully reassembled yet? */
|
||||
if (p == NULL) {
|
||||
return ERR_OK;
|
||||
}
|
||||
iphdr = p->payload;
|
||||
iphdr = (struct ip_hdr *)p->payload;
|
||||
#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
|
||||
pbuf_free(p);
|
||||
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n",
|
||||
@@ -387,7 +531,7 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
|
||||
#if LWIP_IGMP
|
||||
/* there is an extra "router alert" option in IGMP messages which we allow for but do not police */
|
||||
if((iphdr_hlen > IP_HLEN && (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) {
|
||||
if((iphdr_hlen > IP_HLEN) && (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) {
|
||||
#else
|
||||
if (iphdr_hlen > IP_HLEN) {
|
||||
#endif /* LWIP_IGMP */
|
||||
@@ -414,7 +558,6 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
if (raw_input(p, inp) == 0)
|
||||
#endif /* LWIP_RAW */
|
||||
{
|
||||
|
||||
switch (IPH_PROTO(iphdr)) {
|
||||
#if LWIP_UDP
|
||||
case IP_PROTO_UDP:
|
||||
@@ -439,14 +582,14 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
#endif /* LWIP_ICMP */
|
||||
#if LWIP_IGMP
|
||||
case IP_PROTO_IGMP:
|
||||
igmp_input(p,inp,&(iphdr->dest));
|
||||
igmp_input(p, inp, ¤t_iphdr_dest);
|
||||
break;
|
||||
#endif /* LWIP_IGMP */
|
||||
default:
|
||||
#if LWIP_ICMP
|
||||
/* send ICMP destination protocol unreachable unless is was a broadcast */
|
||||
if (!ip_addr_isbroadcast(&(iphdr->dest), inp) &&
|
||||
!ip_addr_ismulticast(&(iphdr->dest))) {
|
||||
if (!ip_addr_isbroadcast(¤t_iphdr_dest, inp) &&
|
||||
!ip_addr_ismulticast(¤t_iphdr_dest)) {
|
||||
p->payload = iphdr;
|
||||
icmp_dest_unreach(p, ICMP_DUR_PROTO);
|
||||
}
|
||||
@@ -463,6 +606,8 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
|
||||
current_netif = NULL;
|
||||
current_header = NULL;
|
||||
ip_addr_set_any(¤t_iphdr_src);
|
||||
ip_addr_set_any(¤t_iphdr_dest);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
@@ -493,7 +638,7 @@ ip_input(struct pbuf *p, struct netif *inp)
|
||||
* unique identifiers independent of destination"
|
||||
*/
|
||||
err_t
|
||||
ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
||||
u8_t ttl, u8_t tos,
|
||||
u8_t proto, struct netif *netif)
|
||||
{
|
||||
@@ -507,13 +652,20 @@ ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
* @ param ip_options pointer to the IP options, copied into the IP header
|
||||
* @ param optlen length of ip_options
|
||||
*/
|
||||
err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options,
|
||||
u16_t optlen)
|
||||
{
|
||||
#endif /* IP_OPTIONS_SEND */
|
||||
struct ip_hdr *iphdr;
|
||||
static u16_t ip_id = 0;
|
||||
ip_addr_t dest_addr;
|
||||
#if CHECKSUM_GEN_IP_INLINE
|
||||
u32_t chk_sum = 0;
|
||||
#endif /* CHECKSUM_GEN_IP_INLINE */
|
||||
|
||||
/* pbufs passed to IP must have a ref-count of 1 as their payload pointer
|
||||
gets altered as the packet is passed down the stack */
|
||||
LWIP_ASSERT("p->ref == 1", p->ref == 1);
|
||||
|
||||
snmp_inc_ipoutrequests();
|
||||
|
||||
@@ -523,6 +675,9 @@ err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest
|
||||
#if IP_OPTIONS_SEND
|
||||
u16_t optlen_aligned = 0;
|
||||
if (optlen != 0) {
|
||||
#if CHECKSUM_GEN_IP_INLINE
|
||||
int i;
|
||||
#endif /* CHECKSUM_GEN_IP_INLINE */
|
||||
/* round up to a multiple of 4 */
|
||||
optlen_aligned = ((optlen + 3) & ~3);
|
||||
ip_hlen += optlen_aligned;
|
||||
@@ -538,6 +693,11 @@ err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest
|
||||
/* zero the remaining bytes */
|
||||
memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen);
|
||||
}
|
||||
#if CHECKSUM_GEN_IP_INLINE
|
||||
for (i = 0; i < optlen_aligned/2; i++) {
|
||||
chk_sum += ((u16_t*)p->payload)[i];
|
||||
}
|
||||
#endif /* CHECKSUM_GEN_IP_INLINE */
|
||||
}
|
||||
#endif /* IP_OPTIONS_SEND */
|
||||
/* generate IP header */
|
||||
@@ -549,35 +709,64 @@ err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
iphdr = p->payload;
|
||||
iphdr = (struct ip_hdr *)p->payload;
|
||||
LWIP_ASSERT("check that first pbuf can hold struct ip_hdr",
|
||||
(p->len >= sizeof(struct ip_hdr)));
|
||||
|
||||
IPH_TTL_SET(iphdr, ttl);
|
||||
IPH_PROTO_SET(iphdr, proto);
|
||||
#if CHECKSUM_GEN_IP_INLINE
|
||||
chk_sum += LWIP_MAKE_U16(proto, ttl);
|
||||
#endif /* CHECKSUM_GEN_IP_INLINE */
|
||||
|
||||
ip_addr_set(&(iphdr->dest), dest);
|
||||
/* dest cannot be NULL here */
|
||||
ip_addr_copy(iphdr->dest, *dest);
|
||||
#if CHECKSUM_GEN_IP_INLINE
|
||||
chk_sum += ip4_addr_get_u32(&iphdr->dest) & 0xFFFF;
|
||||
chk_sum += ip4_addr_get_u32(&iphdr->dest) >> 16;
|
||||
#endif /* CHECKSUM_GEN_IP_INLINE */
|
||||
|
||||
IPH_VHLTOS_SET(iphdr, 4, ip_hlen / 4, tos);
|
||||
IPH_VHL_SET(iphdr, 4, ip_hlen / 4);
|
||||
IPH_TOS_SET(iphdr, tos);
|
||||
#if CHECKSUM_GEN_IP_INLINE
|
||||
chk_sum += LWIP_MAKE_U16(tos, iphdr->_v_hl);
|
||||
#endif /* CHECKSUM_GEN_IP_INLINE */
|
||||
IPH_LEN_SET(iphdr, htons(p->tot_len));
|
||||
#if CHECKSUM_GEN_IP_INLINE
|
||||
chk_sum += iphdr->_len;
|
||||
#endif /* CHECKSUM_GEN_IP_INLINE */
|
||||
IPH_OFFSET_SET(iphdr, 0);
|
||||
IPH_ID_SET(iphdr, htons(ip_id));
|
||||
#if CHECKSUM_GEN_IP_INLINE
|
||||
chk_sum += iphdr->_id;
|
||||
#endif /* CHECKSUM_GEN_IP_INLINE */
|
||||
++ip_id;
|
||||
|
||||
if (ip_addr_isany(src)) {
|
||||
ip_addr_set(&(iphdr->src), &(netif->ip_addr));
|
||||
ip_addr_copy(iphdr->src, netif->ip_addr);
|
||||
} else {
|
||||
ip_addr_set(&(iphdr->src), src);
|
||||
/* src cannot be NULL here */
|
||||
ip_addr_copy(iphdr->src, *src);
|
||||
}
|
||||
|
||||
#if CHECKSUM_GEN_IP_INLINE
|
||||
chk_sum += ip4_addr_get_u32(&iphdr->src) & 0xFFFF;
|
||||
chk_sum += ip4_addr_get_u32(&iphdr->src) >> 16;
|
||||
chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF);
|
||||
chk_sum = (chk_sum >> 16) + chk_sum;
|
||||
chk_sum = ~chk_sum;
|
||||
iphdr->_chksum = chk_sum; /* network order */
|
||||
#else /* CHECKSUM_GEN_IP_INLINE */
|
||||
IPH_CHKSUM_SET(iphdr, 0);
|
||||
#if CHECKSUM_GEN_IP
|
||||
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen));
|
||||
#endif
|
||||
#endif /* CHECKSUM_GEN_IP_INLINE */
|
||||
} else {
|
||||
/* IP header already included in p */
|
||||
iphdr = p->payload;
|
||||
dest = &(iphdr->dest);
|
||||
iphdr = (struct ip_hdr *)p->payload;
|
||||
ip_addr_copy(dest_addr, iphdr->dest);
|
||||
dest = &dest_addr;
|
||||
}
|
||||
|
||||
IP_STATS_INC(ip.xmit);
|
||||
@@ -591,13 +780,18 @@ err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest
|
||||
LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()"));
|
||||
return netif_loop_output(netif, p, dest);
|
||||
}
|
||||
#if LWIP_IGMP
|
||||
if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) {
|
||||
netif_loop_output(netif, p, dest);
|
||||
}
|
||||
#endif /* LWIP_IGMP */
|
||||
#endif /* ENABLE_LOOPBACK */
|
||||
#if IP_FRAG
|
||||
/* don't fragment if interface has mtu set to 0 [loopif] */
|
||||
if (netif->mtu && (p->tot_len > netif->mtu)) {
|
||||
return ip_frag(p,netif,dest);
|
||||
return ip_frag(p, netif, dest);
|
||||
}
|
||||
#endif
|
||||
#endif /* IP_FRAG */
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
|
||||
return netif->output(netif, p, dest);
|
||||
@@ -621,13 +815,18 @@ err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest
|
||||
* see ip_output_if() for more return values
|
||||
*/
|
||||
err_t
|
||||
ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto)
|
||||
{
|
||||
struct netif *netif;
|
||||
|
||||
/* pbufs passed to IP must have a ref-count of 1 as their payload pointer
|
||||
gets altered as the packet is passed down the stack */
|
||||
LWIP_ASSERT("p->ref == 1", p->ref == 1);
|
||||
|
||||
if ((netif = ip_route(dest)) == NULL) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));
|
||||
IP_STATS_INC(ip.rterr);
|
||||
return ERR_RTE;
|
||||
}
|
||||
@@ -655,21 +854,26 @@ ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
* see ip_output_if() for more return values
|
||||
*/
|
||||
err_t
|
||||
ip_output_hinted(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint)
|
||||
{
|
||||
struct netif *netif;
|
||||
err_t err;
|
||||
|
||||
/* pbufs passed to IP must have a ref-count of 1 as their payload pointer
|
||||
gets altered as the packet is passed down the stack */
|
||||
LWIP_ASSERT("p->ref == 1", p->ref == 1);
|
||||
|
||||
if ((netif = ip_route(dest)) == NULL) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to 0x%"X32_F"\n", dest->addr));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_output: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));
|
||||
IP_STATS_INC(ip.rterr);
|
||||
return ERR_RTE;
|
||||
}
|
||||
|
||||
netif->addr_hint = addr_hint;
|
||||
NETIF_SET_HWADDRHINT(netif, addr_hint);
|
||||
err = ip_output_if(p, src, dest, ttl, tos, proto, netif);
|
||||
netif->addr_hint = NULL;
|
||||
NETIF_SET_HWADDRHINT(netif, NULL);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -682,10 +886,7 @@ ip_output_hinted(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
void
|
||||
ip_debug_print(struct pbuf *p)
|
||||
{
|
||||
struct ip_hdr *iphdr = p->payload;
|
||||
u8_t *payload;
|
||||
|
||||
payload = (u8_t *)iphdr + IP_HLEN;
|
||||
struct ip_hdr *iphdr = (struct ip_hdr *)p->payload;
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
@@ -708,16 +909,16 @@ ip_debug_print(struct pbuf *p)
|
||||
ntohs(IPH_CHKSUM(iphdr))));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n",
|
||||
ip4_addr1(&iphdr->src),
|
||||
ip4_addr2(&iphdr->src),
|
||||
ip4_addr3(&iphdr->src),
|
||||
ip4_addr4(&iphdr->src)));
|
||||
ip4_addr1_16(&iphdr->src),
|
||||
ip4_addr2_16(&iphdr->src),
|
||||
ip4_addr3_16(&iphdr->src),
|
||||
ip4_addr4_16(&iphdr->src)));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n",
|
||||
ip4_addr1(&iphdr->dest),
|
||||
ip4_addr2(&iphdr->dest),
|
||||
ip4_addr3(&iphdr->dest),
|
||||
ip4_addr4(&iphdr->dest)));
|
||||
ip4_addr1_16(&iphdr->dest),
|
||||
ip4_addr2_16(&iphdr->dest),
|
||||
ip4_addr3_16(&iphdr->dest),
|
||||
ip4_addr4_16(&iphdr->dest)));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
}
|
||||
#endif /* IP_DEBUG */
|
||||
|
||||
@@ -38,15 +38,11 @@
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
#define IP_ADDR_ANY_VALUE 0x00000000UL
|
||||
#define IP_ADDR_BROADCAST_VALUE 0xffffffffUL
|
||||
|
||||
/* used by IP_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */
|
||||
const struct ip_addr ip_addr_any = { IP_ADDR_ANY_VALUE };
|
||||
const struct ip_addr ip_addr_broadcast = { IP_ADDR_BROADCAST_VALUE };
|
||||
const ip_addr_t ip_addr_any = { IPADDR_ANY };
|
||||
const ip_addr_t ip_addr_broadcast = { IPADDR_BROADCAST };
|
||||
|
||||
/**
|
||||
* Determine if an address is a broadcast address on a network interface
|
||||
@@ -55,30 +51,262 @@ const struct ip_addr ip_addr_broadcast = { IP_ADDR_BROADCAST_VALUE };
|
||||
* @param netif the network interface against which the address is checked
|
||||
* @return returns non-zero if the address is a broadcast address
|
||||
*/
|
||||
u8_t ip_addr_isbroadcast(struct ip_addr *addr, struct netif *netif)
|
||||
u8_t
|
||||
ip4_addr_isbroadcast(u32_t addr, const struct netif *netif)
|
||||
{
|
||||
u32_t addr2test;
|
||||
ip_addr_t ipaddr;
|
||||
ip4_addr_set_u32(&ipaddr, addr);
|
||||
|
||||
addr2test = addr->addr;
|
||||
/* all ones (broadcast) or all zeroes (old skool broadcast) */
|
||||
if ((~addr2test == IP_ADDR_ANY_VALUE) ||
|
||||
(addr2test == IP_ADDR_ANY_VALUE))
|
||||
if ((~addr == IPADDR_ANY) ||
|
||||
(addr == IPADDR_ANY)) {
|
||||
return 1;
|
||||
/* no broadcast support on this network interface? */
|
||||
else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0)
|
||||
} else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0) {
|
||||
/* the given address cannot be a broadcast address
|
||||
* nor can we check against any broadcast addresses */
|
||||
return 0;
|
||||
/* address matches network interface address exactly? => no broadcast */
|
||||
else if (addr2test == netif->ip_addr.addr)
|
||||
} else if (addr == ip4_addr_get_u32(&netif->ip_addr)) {
|
||||
return 0;
|
||||
/* on the same (sub) network... */
|
||||
else if (ip_addr_netcmp(addr, &(netif->ip_addr), &(netif->netmask))
|
||||
} else if (ip_addr_netcmp(&ipaddr, &(netif->ip_addr), &(netif->netmask))
|
||||
/* ...and host identifier bits are all ones? =>... */
|
||||
&& ((addr2test & ~netif->netmask.addr) ==
|
||||
(IP_ADDR_BROADCAST_VALUE & ~netif->netmask.addr)))
|
||||
&& ((addr & ~ip4_addr_get_u32(&netif->netmask)) ==
|
||||
(IPADDR_BROADCAST & ~ip4_addr_get_u32(&netif->netmask)))) {
|
||||
/* => network broadcast address */
|
||||
return 1;
|
||||
else
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Checks if a netmask is valid (starting with ones, then only zeros)
|
||||
*
|
||||
* @param netmask the IPv4 netmask to check (in network byte order!)
|
||||
* @return 1 if the netmask is valid, 0 if it is not
|
||||
*/
|
||||
u8_t
|
||||
ip4_addr_netmask_valid(u32_t netmask)
|
||||
{
|
||||
u32_t mask;
|
||||
u32_t nm_hostorder = lwip_htonl(netmask);
|
||||
|
||||
/* first, check for the first zero */
|
||||
for (mask = 1UL << 31 ; mask != 0; mask >>= 1) {
|
||||
if ((nm_hostorder & mask) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* then check that there is no one */
|
||||
for (; mask != 0; mask >>= 1) {
|
||||
if ((nm_hostorder & mask) != 0) {
|
||||
/* there is a one after the first zero -> invalid */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* no one after the first zero -> valid */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Here for now until needed in other places in lwIP */
|
||||
#ifndef isprint
|
||||
#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up)
|
||||
#define isprint(c) in_range(c, 0x20, 0x7f)
|
||||
#define isdigit(c) in_range(c, '0', '9')
|
||||
#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
|
||||
#define islower(c) in_range(c, 'a', 'z')
|
||||
#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Ascii internet address interpretation routine.
|
||||
* The value returned is in network order.
|
||||
*
|
||||
* @param cp IP address in ascii represenation (e.g. "127.0.0.1")
|
||||
* @return ip address in network order
|
||||
*/
|
||||
u32_t
|
||||
ipaddr_addr(const char *cp)
|
||||
{
|
||||
ip_addr_t val;
|
||||
|
||||
if (ipaddr_aton(cp, &val)) {
|
||||
return ip4_addr_get_u32(&val);
|
||||
}
|
||||
return (IPADDR_NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether "cp" is a valid ascii representation
|
||||
* of an Internet address and convert to a binary address.
|
||||
* Returns 1 if the address is valid, 0 if not.
|
||||
* This replaces inet_addr, the return value from which
|
||||
* cannot distinguish between failure and a local broadcast address.
|
||||
*
|
||||
* @param cp IP address in ascii represenation (e.g. "127.0.0.1")
|
||||
* @param addr pointer to which to save the ip address in network order
|
||||
* @return 1 if cp could be converted to addr, 0 on failure
|
||||
*/
|
||||
int
|
||||
ipaddr_aton(const char *cp, ip_addr_t *addr)
|
||||
{
|
||||
u32_t val;
|
||||
u8_t base;
|
||||
char c;
|
||||
u32_t parts[4];
|
||||
u32_t *pp = parts;
|
||||
|
||||
c = *cp;
|
||||
for (;;) {
|
||||
/*
|
||||
* Collect number up to ``.''.
|
||||
* Values are specified as for C:
|
||||
* 0x=hex, 0=octal, 1-9=decimal.
|
||||
*/
|
||||
if (!isdigit(c))
|
||||
return (0);
|
||||
val = 0;
|
||||
base = 10;
|
||||
if (c == '0') {
|
||||
c = *++cp;
|
||||
if (c == 'x' || c == 'X') {
|
||||
base = 16;
|
||||
c = *++cp;
|
||||
} else
|
||||
base = 8;
|
||||
}
|
||||
for (;;) {
|
||||
if (isdigit(c)) {
|
||||
val = (val * base) + (int)(c - '0');
|
||||
c = *++cp;
|
||||
} else if (base == 16 && isxdigit(c)) {
|
||||
val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A'));
|
||||
c = *++cp;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
if (c == '.') {
|
||||
/*
|
||||
* Internet format:
|
||||
* a.b.c.d
|
||||
* a.b.c (with c treated as 16 bits)
|
||||
* a.b (with b treated as 24 bits)
|
||||
*/
|
||||
if (pp >= parts + 3) {
|
||||
return (0);
|
||||
}
|
||||
*pp++ = val;
|
||||
c = *++cp;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Check for trailing characters.
|
||||
*/
|
||||
if (c != '\0' && !isspace(c)) {
|
||||
return (0);
|
||||
}
|
||||
/*
|
||||
* Concoct the address according to
|
||||
* the number of parts specified.
|
||||
*/
|
||||
switch (pp - parts + 1) {
|
||||
|
||||
case 0:
|
||||
return (0); /* initial nondigit */
|
||||
|
||||
case 1: /* a -- 32 bits */
|
||||
break;
|
||||
|
||||
case 2: /* a.b -- 8.24 bits */
|
||||
if (val > 0xffffffUL) {
|
||||
return (0);
|
||||
}
|
||||
val |= parts[0] << 24;
|
||||
break;
|
||||
|
||||
case 3: /* a.b.c -- 8.8.16 bits */
|
||||
if (val > 0xffff) {
|
||||
return (0);
|
||||
}
|
||||
val |= (parts[0] << 24) | (parts[1] << 16);
|
||||
break;
|
||||
|
||||
case 4: /* a.b.c.d -- 8.8.8.8 bits */
|
||||
if (val > 0xff) {
|
||||
return (0);
|
||||
}
|
||||
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
|
||||
break;
|
||||
default:
|
||||
LWIP_ASSERT("unhandled", 0);
|
||||
break;
|
||||
}
|
||||
if (addr) {
|
||||
ip4_addr_set_u32(addr, htonl(val));
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert numeric IP address into decimal dotted ASCII representation.
|
||||
* returns ptr to static buffer; not reentrant!
|
||||
*
|
||||
* @param addr ip address in network order to convert
|
||||
* @return pointer to a global static (!) buffer that holds the ASCII
|
||||
* represenation of addr
|
||||
*/
|
||||
char *
|
||||
ipaddr_ntoa(const ip_addr_t *addr)
|
||||
{
|
||||
static char str[16];
|
||||
return ipaddr_ntoa_r(addr, str, 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used.
|
||||
*
|
||||
* @param addr ip address in network order to convert
|
||||
* @param buf target buffer where the string is stored
|
||||
* @param buflen length of buf
|
||||
* @return either pointer to buf which now holds the ASCII
|
||||
* representation of addr or NULL if buf was too small
|
||||
*/
|
||||
char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen)
|
||||
{
|
||||
u32_t s_addr;
|
||||
char inv[3];
|
||||
char *rp;
|
||||
u8_t *ap;
|
||||
u8_t rem;
|
||||
u8_t n;
|
||||
u8_t i;
|
||||
int len = 0;
|
||||
|
||||
s_addr = ip4_addr_get_u32(addr);
|
||||
|
||||
rp = buf;
|
||||
ap = (u8_t *)&s_addr;
|
||||
for(n = 0; n < 4; n++) {
|
||||
i = 0;
|
||||
do {
|
||||
rem = *ap % (u8_t)10;
|
||||
*ap /= (u8_t)10;
|
||||
inv[i++] = '0' + rem;
|
||||
} while(*ap);
|
||||
while(i--) {
|
||||
if (len++ >= buflen) {
|
||||
return NULL;
|
||||
}
|
||||
*rp++ = inv[i];
|
||||
}
|
||||
if (len++ >= buflen) {
|
||||
return NULL;
|
||||
}
|
||||
*rp++ = '.';
|
||||
ap++;
|
||||
}
|
||||
*--rp = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
@@ -40,8 +40,7 @@
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/ip_frag.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/snmp.h"
|
||||
@@ -81,7 +80,10 @@
|
||||
/** This is a helper struct which holds the starting
|
||||
* offset and the ending offset of this fragment to
|
||||
* easily chain the fragments.
|
||||
* It has to be packed since it has to fit inside the IP header.
|
||||
* It has the same packing requirements as the IP header, since it replaces
|
||||
* the IP header in memory in incoming fragments (after copying it) to keep
|
||||
* track of the various fragments. (-> If the IP header doesn't need packing,
|
||||
* this struct doesn't need packing, too.)
|
||||
*/
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
@@ -155,7 +157,8 @@ ip_reass_tmr(void)
|
||||
static int
|
||||
ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev)
|
||||
{
|
||||
int pbufs_freed = 0;
|
||||
u16_t pbufs_freed = 0;
|
||||
u8_t clen;
|
||||
struct pbuf *p;
|
||||
struct ip_reass_helper *iprh;
|
||||
|
||||
@@ -175,7 +178,9 @@ ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *p
|
||||
/* Then, copy the original header into it. */
|
||||
SMEMCPY(p->payload, &ipr->iphdr, IP_HLEN);
|
||||
icmp_time_exceeded(p, ICMP_TE_FRAG);
|
||||
pbufs_freed += pbuf_clen(p);
|
||||
clen = pbuf_clen(p);
|
||||
LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
|
||||
pbufs_freed += clen;
|
||||
pbuf_free(p);
|
||||
}
|
||||
#endif /* LWIP_ICMP */
|
||||
@@ -189,8 +194,10 @@ ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *p
|
||||
pcur = p;
|
||||
/* get the next pointer before freeing */
|
||||
p = iprh->next_pbuf;
|
||||
pbufs_freed += pbuf_clen(pcur);
|
||||
pbuf_free(pcur);
|
||||
clen = pbuf_clen(pcur);
|
||||
LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
|
||||
pbufs_freed += clen;
|
||||
pbuf_free(pcur);
|
||||
}
|
||||
/* Then, unchain the struct ip_reassdata from the list and free it. */
|
||||
ip_reass_dequeue_datagram(ipr, prev);
|
||||
@@ -263,11 +270,11 @@ ip_reass_enqueue_new_datagram(struct ip_hdr *fraghdr, int clen)
|
||||
{
|
||||
struct ip_reassdata* ipr;
|
||||
/* No matching previous fragment found, allocate a new reassdata struct */
|
||||
ipr = memp_malloc(MEMP_REASSDATA);
|
||||
ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA);
|
||||
if (ipr == NULL) {
|
||||
#if IP_REASS_FREE_OLDEST
|
||||
if (ip_reass_remove_oldest_datagram(fraghdr, clen) >= clen) {
|
||||
ipr = memp_malloc(MEMP_REASSDATA);
|
||||
ipr = (struct ip_reassdata *)memp_malloc(MEMP_REASSDATA);
|
||||
}
|
||||
if (ipr == NULL)
|
||||
#endif /* IP_REASS_FREE_OLDEST */
|
||||
@@ -548,7 +555,7 @@ ip_reass(struct pbuf *p)
|
||||
* to an existing one */
|
||||
|
||||
/* check for 'no more fragments', and update queue entry*/
|
||||
if ((ntohs(IPH_OFFSET(fraghdr)) & IP_MF) == 0) {
|
||||
if ((IPH_OFFSET(fraghdr) & PP_NTOHS(IP_MF)) == 0) {
|
||||
ipr->flags |= IP_REASS_FLAG_LASTFRAG;
|
||||
ipr->datagram_len = offset + len;
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
@@ -609,6 +616,38 @@ nullreturn:
|
||||
#if IP_FRAG
|
||||
#if IP_FRAG_USES_STATIC_BUF
|
||||
static u8_t buf[LWIP_MEM_ALIGN_SIZE(IP_FRAG_MAX_MTU + MEM_ALIGNMENT - 1)];
|
||||
#else /* IP_FRAG_USES_STATIC_BUF */
|
||||
|
||||
#if !LWIP_NETIF_TX_SINGLE_PBUF
|
||||
/** Allocate a new struct pbuf_custom_ref */
|
||||
static struct pbuf_custom_ref*
|
||||
ip_frag_alloc_pbuf_custom_ref(void)
|
||||
{
|
||||
return (struct pbuf_custom_ref*)memp_malloc(MEMP_FRAG_PBUF);
|
||||
}
|
||||
|
||||
/** Free a struct pbuf_custom_ref */
|
||||
static void
|
||||
ip_frag_free_pbuf_custom_ref(struct pbuf_custom_ref* p)
|
||||
{
|
||||
LWIP_ASSERT("p != NULL", p != NULL);
|
||||
memp_free(MEMP_FRAG_PBUF, p);
|
||||
}
|
||||
|
||||
/** Free-callback function to free a 'struct pbuf_custom_ref', called by
|
||||
* pbuf_free. */
|
||||
static void
|
||||
ipfrag_free_pbuf_custom(struct pbuf *p)
|
||||
{
|
||||
struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref*)p;
|
||||
LWIP_ASSERT("pcr != NULL", pcr != NULL);
|
||||
LWIP_ASSERT("pcr == p", (void*)pcr == (void*)p);
|
||||
if (pcr->original != NULL) {
|
||||
pbuf_free(pcr->original);
|
||||
}
|
||||
ip_frag_free_pbuf_custom_ref(pcr);
|
||||
}
|
||||
#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */
|
||||
#endif /* IP_FRAG_USES_STATIC_BUF */
|
||||
|
||||
/**
|
||||
@@ -625,13 +664,15 @@ static u8_t buf[LWIP_MEM_ALIGN_SIZE(IP_FRAG_MAX_MTU + MEM_ALIGNMENT - 1)];
|
||||
* @return ERR_OK if sent successfully, err_t otherwise
|
||||
*/
|
||||
err_t
|
||||
ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
|
||||
ip_frag(struct pbuf *p, struct netif *netif, ip_addr_t *dest)
|
||||
{
|
||||
struct pbuf *rambuf;
|
||||
#if IP_FRAG_USES_STATIC_BUF
|
||||
struct pbuf *header;
|
||||
#else
|
||||
#if !LWIP_NETIF_TX_SINGLE_PBUF
|
||||
struct pbuf *newpbuf;
|
||||
#endif
|
||||
struct ip_hdr *original_iphdr;
|
||||
#endif
|
||||
struct ip_hdr *iphdr;
|
||||
@@ -642,7 +683,7 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
|
||||
u16_t last;
|
||||
u16_t poff = IP_HLEN;
|
||||
u16_t tmp;
|
||||
#if !IP_FRAG_USES_STATIC_BUF
|
||||
#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF
|
||||
u16_t newpbuflen = 0;
|
||||
u16_t left_to_copy;
|
||||
#endif
|
||||
@@ -662,10 +703,10 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
|
||||
rambuf->payload = LWIP_MEM_ALIGN((void *)buf);
|
||||
|
||||
/* Copy the IP header in it */
|
||||
iphdr = rambuf->payload;
|
||||
iphdr = (struct ip_hdr *)rambuf->payload;
|
||||
SMEMCPY(iphdr, p->payload, IP_HLEN);
|
||||
#else /* IP_FRAG_USES_STATIC_BUF */
|
||||
original_iphdr = p->payload;
|
||||
original_iphdr = (struct ip_hdr *)p->payload;
|
||||
iphdr = original_iphdr;
|
||||
#endif /* IP_FRAG_USES_STATIC_BUF */
|
||||
|
||||
@@ -683,8 +724,9 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
|
||||
|
||||
/* Set new offset and MF flag */
|
||||
tmp = omf | (IP_OFFMASK & (ofo));
|
||||
if (!last)
|
||||
if (!last) {
|
||||
tmp = tmp | IP_MF;
|
||||
}
|
||||
|
||||
/* Fill this fragment */
|
||||
cop = last ? left : nfb * 8;
|
||||
@@ -692,6 +734,23 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
|
||||
#if IP_FRAG_USES_STATIC_BUF
|
||||
poff += pbuf_copy_partial(p, (u8_t*)iphdr + IP_HLEN, cop, poff);
|
||||
#else /* IP_FRAG_USES_STATIC_BUF */
|
||||
#if LWIP_NETIF_TX_SINGLE_PBUF
|
||||
rambuf = pbuf_alloc(PBUF_IP, cop, PBUF_RAM);
|
||||
if (rambuf == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
LWIP_ASSERT("this needs a pbuf in one piece!",
|
||||
(rambuf->len == rambuf->tot_len) && (rambuf->next == NULL));
|
||||
poff += pbuf_copy_partial(p, rambuf->payload, cop, poff);
|
||||
/* make room for the IP header */
|
||||
if(pbuf_header(rambuf, IP_HLEN)) {
|
||||
pbuf_free(rambuf);
|
||||
return ERR_MEM;
|
||||
}
|
||||
/* fill in the IP header */
|
||||
SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN);
|
||||
iphdr = rambuf->payload;
|
||||
#else /* LWIP_NETIF_TX_SINGLE_PBUF */
|
||||
/* When not using a static buffer, create a chain of pbufs.
|
||||
* The first will be a PBUF_RAM holding the link and IP header.
|
||||
* The rest will be PBUF_REFs mirroring the pbuf chain to be fragged,
|
||||
@@ -704,7 +763,7 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
|
||||
LWIP_ASSERT("this needs a pbuf in one piece!",
|
||||
(p->len >= (IP_HLEN)));
|
||||
SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN);
|
||||
iphdr = rambuf->payload;
|
||||
iphdr = (struct ip_hdr *)rambuf->payload;
|
||||
|
||||
/* Can just adjust p directly for needed offset. */
|
||||
p->payload = (u8_t *)p->payload + poff;
|
||||
@@ -712,29 +771,40 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
|
||||
|
||||
left_to_copy = cop;
|
||||
while (left_to_copy) {
|
||||
struct pbuf_custom_ref *pcr;
|
||||
newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len;
|
||||
/* Is this pbuf already empty? */
|
||||
if (!newpbuflen) {
|
||||
p = p->next;
|
||||
continue;
|
||||
}
|
||||
newpbuf = pbuf_alloc(PBUF_RAW, 0, PBUF_REF);
|
||||
if (newpbuf == NULL) {
|
||||
pcr = ip_frag_alloc_pbuf_custom_ref();
|
||||
if (pcr == NULL) {
|
||||
pbuf_free(rambuf);
|
||||
return ERR_MEM;
|
||||
}
|
||||
/* Mirror this pbuf, although we might not need all of it. */
|
||||
newpbuf->payload = p->payload;
|
||||
newpbuf->len = newpbuf->tot_len = newpbuflen;
|
||||
newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen);
|
||||
if (newpbuf == NULL) {
|
||||
ip_frag_free_pbuf_custom_ref(pcr);
|
||||
pbuf_free(rambuf);
|
||||
return ERR_MEM;
|
||||
}
|
||||
pbuf_ref(p);
|
||||
pcr->original = p;
|
||||
pcr->pc.custom_free_function = ipfrag_free_pbuf_custom;
|
||||
|
||||
/* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain
|
||||
* so that it is removed when pbuf_dechain is later called on rambuf.
|
||||
*/
|
||||
pbuf_cat(rambuf, newpbuf);
|
||||
left_to_copy -= newpbuflen;
|
||||
if (left_to_copy)
|
||||
if (left_to_copy) {
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
poff = newpbuflen;
|
||||
#endif /* LWIP_NETIF_TX_SINGLE_PBUF */
|
||||
#endif /* IP_FRAG_USES_STATIC_BUF */
|
||||
|
||||
/* Correct header */
|
||||
@@ -744,8 +814,9 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
|
||||
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
|
||||
|
||||
#if IP_FRAG_USES_STATIC_BUF
|
||||
if (last)
|
||||
if (last) {
|
||||
pbuf_realloc(rambuf, left + IP_HLEN);
|
||||
}
|
||||
|
||||
/* This part is ugly: we alloc a RAM based pbuf for
|
||||
* the link level header for each chunk and then
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/icmp.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/tcp_impl.h"
|
||||
|
||||
#include "lwip/stats.h"
|
||||
|
||||
@@ -341,9 +341,9 @@ ip_output_hinted(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
return ERR_RTE;
|
||||
}
|
||||
|
||||
netif->addr_hint = addr_hint;
|
||||
LWIP_NETIF_HWADDRHINT(netif, addr_hint);
|
||||
err = ip_output_if(p, src, dest, ttl, tos, proto, netif);
|
||||
netif->addr_hint = NULL;
|
||||
LWIP_NETIF_HWADDRHINT(netif, NULL);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
140
src/core/mem.c
140
src/core/mem.c
@@ -61,6 +61,7 @@
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/err.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -77,11 +78,12 @@
|
||||
void *
|
||||
mem_malloc(mem_size_t size)
|
||||
{
|
||||
void *ret;
|
||||
struct memp_malloc_helper *element;
|
||||
memp_t poolnr;
|
||||
mem_size_t required_size = size + sizeof(struct memp_malloc_helper);
|
||||
mem_size_t required_size = size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper));
|
||||
|
||||
for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr++) {
|
||||
for (poolnr = MEMP_POOL_FIRST; poolnr <= MEMP_POOL_LAST; poolnr = (memp_t)(poolnr + 1)) {
|
||||
#if MEM_USE_POOLS_TRY_BIGGER_POOL
|
||||
again:
|
||||
#endif /* MEM_USE_POOLS_TRY_BIGGER_POOL */
|
||||
@@ -112,9 +114,9 @@ again:
|
||||
/* save the pool number this element came from */
|
||||
element->poolnr = poolnr;
|
||||
/* and return a pointer to the memory directly after the struct memp_malloc_helper */
|
||||
element++;
|
||||
ret = (u8_t*)element + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper));
|
||||
|
||||
return element;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,13 +129,13 @@ again:
|
||||
void
|
||||
mem_free(void *rmem)
|
||||
{
|
||||
struct memp_malloc_helper *hmem = (struct memp_malloc_helper*)rmem;
|
||||
struct memp_malloc_helper *hmem;
|
||||
|
||||
LWIP_ASSERT("rmem != NULL", (rmem != NULL));
|
||||
LWIP_ASSERT("rmem == MEM_ALIGN(rmem)", (rmem == LWIP_MEM_ALIGN(rmem)));
|
||||
|
||||
/* get the original struct memp_malloc_helper */
|
||||
hmem--;
|
||||
hmem = (struct memp_malloc_helper*)(void*)((u8_t*)rmem - LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)));
|
||||
|
||||
LWIP_ASSERT("hmem != NULL", (hmem != NULL));
|
||||
LWIP_ASSERT("hmem == MEM_ALIGN(hmem)", (hmem == LWIP_MEM_ALIGN(hmem)));
|
||||
@@ -154,7 +156,7 @@ mem_free(void *rmem)
|
||||
struct mem {
|
||||
/** index (-> ram[next]) of the next struct */
|
||||
mem_size_t next;
|
||||
/** index (-> ram[next]) of the next struct */
|
||||
/** index (-> ram[prev]) of the previous struct */
|
||||
mem_size_t prev;
|
||||
/** 1: this area is used; 0: this area is unused */
|
||||
u8_t used;
|
||||
@@ -171,8 +173,16 @@ struct mem {
|
||||
#define SIZEOF_STRUCT_MEM LWIP_MEM_ALIGN_SIZE(sizeof(struct mem))
|
||||
#define MEM_SIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(MEM_SIZE)
|
||||
|
||||
/** If you want to relocate the heap to external memory, simply define
|
||||
* LWIP_RAM_HEAP_POINTER as a void-pointer to that location.
|
||||
* If so, make sure the memory at that location is big enough (see below on
|
||||
* how that space is calculated). */
|
||||
#ifndef LWIP_RAM_HEAP_POINTER
|
||||
/** the heap. we need one struct mem at the end and some room for alignment */
|
||||
static u8_t ram_heap[MEM_SIZE_ALIGNED + (2*SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT];
|
||||
u8_t ram_heap[MEM_SIZE_ALIGNED + (2*SIZEOF_STRUCT_MEM) + MEM_ALIGNMENT];
|
||||
#define LWIP_RAM_HEAP_POINTER ram_heap
|
||||
#endif /* LWIP_RAM_HEAP_POINTER */
|
||||
|
||||
/** pointer to the heap (ram_heap): for alignment, ram is now a pointer instead of an array */
|
||||
static u8_t *ram;
|
||||
/** the last entry, always unused! */
|
||||
@@ -181,7 +191,9 @@ static struct mem *ram_end;
|
||||
static struct mem *lfree;
|
||||
|
||||
/** concurrent access protection */
|
||||
static sys_sem_t mem_sem;
|
||||
#if !NO_SYS
|
||||
static sys_mutex_t mem_mutex;
|
||||
#endif
|
||||
|
||||
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
|
||||
|
||||
@@ -199,8 +211,8 @@ static volatile u8_t mem_free_count;
|
||||
|
||||
/* Protect the heap only by using a semaphore */
|
||||
#define LWIP_MEM_FREE_DECL_PROTECT()
|
||||
#define LWIP_MEM_FREE_PROTECT() sys_arch_sem_wait(mem_sem, 0)
|
||||
#define LWIP_MEM_FREE_UNPROTECT() sys_sem_signal(mem_sem)
|
||||
#define LWIP_MEM_FREE_PROTECT() sys_mutex_lock(&mem_mutex)
|
||||
#define LWIP_MEM_FREE_UNPROTECT() sys_mutex_unlock(&mem_mutex)
|
||||
/* mem_malloc is protected using semaphore AND LWIP_MEM_ALLOC_PROTECT */
|
||||
#define LWIP_MEM_ALLOC_DECL_PROTECT()
|
||||
#define LWIP_MEM_ALLOC_PROTECT()
|
||||
@@ -215,7 +227,7 @@ static volatile u8_t mem_free_count;
|
||||
* one empty struct mem pointing to another empty struct mem.
|
||||
*
|
||||
* @param mem this points to a struct mem which just has been freed
|
||||
* @internal this function is only called by mem_free() and mem_realloc()
|
||||
* @internal this function is only called by mem_free() and mem_trim()
|
||||
*
|
||||
* This assumes access to the heap is protected by the calling function
|
||||
* already.
|
||||
@@ -233,25 +245,25 @@ plug_holes(struct mem *mem)
|
||||
/* plug hole forward */
|
||||
LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE_ALIGNED", mem->next <= MEM_SIZE_ALIGNED);
|
||||
|
||||
nmem = (struct mem *)&ram[mem->next];
|
||||
nmem = (struct mem *)(void *)&ram[mem->next];
|
||||
if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) {
|
||||
/* if mem->next is unused and not end of ram, combine mem and mem->next */
|
||||
if (lfree == nmem) {
|
||||
lfree = mem;
|
||||
}
|
||||
mem->next = nmem->next;
|
||||
((struct mem *)&ram[nmem->next])->prev = (u8_t *)mem - ram;
|
||||
((struct mem *)(void *)&ram[nmem->next])->prev = (mem_size_t)((u8_t *)mem - ram);
|
||||
}
|
||||
|
||||
/* plug hole backward */
|
||||
pmem = (struct mem *)&ram[mem->prev];
|
||||
pmem = (struct mem *)(void *)&ram[mem->prev];
|
||||
if (pmem != mem && pmem->used == 0) {
|
||||
/* if mem->prev is unused, combine mem and mem->prev */
|
||||
if (lfree == mem) {
|
||||
lfree = pmem;
|
||||
}
|
||||
pmem->next = mem->next;
|
||||
((struct mem *)&ram[mem->next])->prev = (u8_t *)pmem - ram;
|
||||
((struct mem *)(void *)&ram[mem->next])->prev = (mem_size_t)((u8_t *)pmem - ram);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,24 +279,26 @@ mem_init(void)
|
||||
(SIZEOF_STRUCT_MEM & (MEM_ALIGNMENT-1)) == 0);
|
||||
|
||||
/* align the heap */
|
||||
ram = LWIP_MEM_ALIGN(ram_heap);
|
||||
ram = (u8_t *)LWIP_MEM_ALIGN(LWIP_RAM_HEAP_POINTER);
|
||||
/* initialize the start of the heap */
|
||||
mem = (struct mem *)ram;
|
||||
mem = (struct mem *)(void *)ram;
|
||||
mem->next = MEM_SIZE_ALIGNED;
|
||||
mem->prev = 0;
|
||||
mem->used = 0;
|
||||
/* initialize the end of the heap */
|
||||
ram_end = (struct mem *)&ram[MEM_SIZE_ALIGNED];
|
||||
ram_end = (struct mem *)(void *)&ram[MEM_SIZE_ALIGNED];
|
||||
ram_end->used = 1;
|
||||
ram_end->next = MEM_SIZE_ALIGNED;
|
||||
ram_end->prev = MEM_SIZE_ALIGNED;
|
||||
|
||||
mem_sem = sys_sem_new(1);
|
||||
|
||||
/* initialize the lowest-free pointer to the start of the heap */
|
||||
lfree = (struct mem *)ram;
|
||||
lfree = (struct mem *)(void *)ram;
|
||||
|
||||
MEM_STATS_AVAIL(avail, MEM_SIZE_ALIGNED);
|
||||
|
||||
if(sys_mutex_new(&mem_mutex) != ERR_OK) {
|
||||
LWIP_ASSERT("failed to create mem_mutex", 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -320,7 +334,7 @@ mem_free(void *rmem)
|
||||
/* protect the heap from concurrent access */
|
||||
LWIP_MEM_FREE_PROTECT();
|
||||
/* Get the corresponding struct mem ... */
|
||||
mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
|
||||
mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
|
||||
/* ... which has to be in a used state ... */
|
||||
LWIP_ASSERT("mem_free: mem->used", mem->used);
|
||||
/* ... and is now unused. */
|
||||
@@ -331,7 +345,7 @@ mem_free(void *rmem)
|
||||
lfree = mem;
|
||||
}
|
||||
|
||||
MEM_STATS_DEC_USED(used, mem->next - ((u8_t *)mem - ram));
|
||||
MEM_STATS_DEC_USED(used, mem->next - (mem_size_t)(((u8_t *)mem - ram)));
|
||||
|
||||
/* finally, see if prev or next are free also */
|
||||
plug_holes(mem);
|
||||
@@ -342,9 +356,7 @@ mem_free(void *rmem)
|
||||
}
|
||||
|
||||
/**
|
||||
* In contrast to its name, mem_realloc can only shrink memory, not expand it.
|
||||
* Since the only use (for now) is in pbuf_realloc (which also can only shrink),
|
||||
* this shouldn't be a problem!
|
||||
* Shrink memory returned by mem_malloc().
|
||||
*
|
||||
* @param rmem pointer to memory allocated by mem_malloc the is to be shrinked
|
||||
* @param newsize required size after shrinking (needs to be smaller than or
|
||||
@@ -354,7 +366,7 @@ mem_free(void *rmem)
|
||||
* or freed!
|
||||
*/
|
||||
void *
|
||||
mem_realloc(void *rmem, mem_size_t newsize)
|
||||
mem_trim(void *rmem, mem_size_t newsize)
|
||||
{
|
||||
mem_size_t size;
|
||||
mem_size_t ptr, ptr2;
|
||||
@@ -375,12 +387,12 @@ mem_realloc(void *rmem, mem_size_t newsize)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LWIP_ASSERT("mem_realloc: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
|
||||
LWIP_ASSERT("mem_trim: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
|
||||
(u8_t *)rmem < (u8_t *)ram_end);
|
||||
|
||||
if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
|
||||
SYS_ARCH_DECL_PROTECT(lev);
|
||||
LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_realloc: illegal memory\n"));
|
||||
LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SEVERE, ("mem_trim: illegal memory\n"));
|
||||
/* protect mem stats from concurrent access */
|
||||
SYS_ARCH_PROTECT(lev);
|
||||
MEM_STATS_INC(illegal);
|
||||
@@ -388,12 +400,12 @@ mem_realloc(void *rmem, mem_size_t newsize)
|
||||
return rmem;
|
||||
}
|
||||
/* Get the corresponding struct mem ... */
|
||||
mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
|
||||
mem = (struct mem *)(void *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
|
||||
/* ... and its offset pointer */
|
||||
ptr = (u8_t *)mem - ram;
|
||||
ptr = (mem_size_t)((u8_t *)mem - ram);
|
||||
|
||||
size = mem->next - ptr - SIZEOF_STRUCT_MEM;
|
||||
LWIP_ASSERT("mem_realloc can only shrink memory", newsize <= size);
|
||||
LWIP_ASSERT("mem_trim can only shrink memory", newsize <= size);
|
||||
if (newsize > size) {
|
||||
/* not supported */
|
||||
return NULL;
|
||||
@@ -406,9 +418,7 @@ mem_realloc(void *rmem, mem_size_t newsize)
|
||||
/* protect the heap from concurrent access */
|
||||
LWIP_MEM_FREE_PROTECT();
|
||||
|
||||
MEM_STATS_DEC_USED(used, (size - newsize));
|
||||
|
||||
mem2 = (struct mem *)&ram[mem->next];
|
||||
mem2 = (struct mem *)(void *)&ram[mem->next];
|
||||
if(mem2->used == 0) {
|
||||
/* The next struct is unused, we can simply move it at little */
|
||||
mem_size_t next;
|
||||
@@ -417,9 +427,9 @@ mem_realloc(void *rmem, mem_size_t newsize)
|
||||
/* create new struct mem which is moved directly after the shrinked mem */
|
||||
ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
|
||||
if (lfree == mem2) {
|
||||
lfree = (struct mem *)&ram[ptr2];
|
||||
lfree = (struct mem *)(void *)&ram[ptr2];
|
||||
}
|
||||
mem2 = (struct mem *)&ram[ptr2];
|
||||
mem2 = (struct mem *)(void *)&ram[ptr2];
|
||||
mem2->used = 0;
|
||||
/* restore the next pointer */
|
||||
mem2->next = next;
|
||||
@@ -431,8 +441,9 @@ mem_realloc(void *rmem, mem_size_t newsize)
|
||||
* let 'mem2->next->prev' point to mem2 again. but only if mem2->next is not
|
||||
* the end of the heap */
|
||||
if (mem2->next != MEM_SIZE_ALIGNED) {
|
||||
((struct mem *)&ram[mem2->next])->prev = ptr2;
|
||||
((struct mem *)(void *)&ram[mem2->next])->prev = ptr2;
|
||||
}
|
||||
MEM_STATS_DEC_USED(used, (size - newsize));
|
||||
/* no need to plug holes, we've already done that */
|
||||
} else if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED <= size) {
|
||||
/* Next struct is used but there's room for another struct mem with
|
||||
@@ -443,7 +454,7 @@ mem_realloc(void *rmem, mem_size_t newsize)
|
||||
* region that couldn't hold data, but when mem->next gets freed,
|
||||
* the 2 regions would be combined, resulting in more free memory */
|
||||
ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
|
||||
mem2 = (struct mem *)&ram[ptr2];
|
||||
mem2 = (struct mem *)(void *)&ram[ptr2];
|
||||
if (mem2 < lfree) {
|
||||
lfree = mem2;
|
||||
}
|
||||
@@ -452,8 +463,9 @@ mem_realloc(void *rmem, mem_size_t newsize)
|
||||
mem2->prev = ptr;
|
||||
mem->next = ptr2;
|
||||
if (mem2->next != MEM_SIZE_ALIGNED) {
|
||||
((struct mem *)&ram[mem2->next])->prev = ptr2;
|
||||
((struct mem *)(void *)&ram[mem2->next])->prev = ptr2;
|
||||
}
|
||||
MEM_STATS_DEC_USED(used, (size - newsize));
|
||||
/* the original mem->next is used, so no need to plug holes! */
|
||||
}
|
||||
/* else {
|
||||
@@ -506,10 +518,10 @@ mem_malloc(mem_size_t size)
|
||||
}
|
||||
|
||||
/* protect the heap from concurrent access */
|
||||
sys_arch_sem_wait(mem_sem, 0);
|
||||
sys_mutex_lock(&mem_mutex);
|
||||
LWIP_MEM_ALLOC_PROTECT();
|
||||
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
|
||||
/* run as long as a mem_free disturbed mem_malloc */
|
||||
/* run as long as a mem_free disturbed mem_malloc or mem_trim */
|
||||
do {
|
||||
local_mem_free_count = 0;
|
||||
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
|
||||
@@ -517,18 +529,20 @@ mem_malloc(mem_size_t size)
|
||||
/* Scan through the heap searching for a free block that is big enough,
|
||||
* beginning with the lowest free block.
|
||||
*/
|
||||
for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE_ALIGNED - size;
|
||||
ptr = ((struct mem *)&ram[ptr])->next) {
|
||||
mem = (struct mem *)&ram[ptr];
|
||||
for (ptr = (mem_size_t)((u8_t *)lfree - ram); ptr < MEM_SIZE_ALIGNED - size;
|
||||
ptr = ((struct mem *)(void *)&ram[ptr])->next) {
|
||||
mem = (struct mem *)(void *)&ram[ptr];
|
||||
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
|
||||
mem_free_count = 0;
|
||||
LWIP_MEM_ALLOC_UNPROTECT();
|
||||
/* allow mem_free to run */
|
||||
/* allow mem_free or mem_trim to run */
|
||||
LWIP_MEM_ALLOC_PROTECT();
|
||||
if (mem_free_count != 0) {
|
||||
local_mem_free_count = mem_free_count;
|
||||
/* If mem_free or mem_trim have run, we have to restart since they
|
||||
could have altered our current struct mem. */
|
||||
local_mem_free_count = 1;
|
||||
break;
|
||||
}
|
||||
mem_free_count = 0;
|
||||
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
|
||||
|
||||
if ((!mem->used) &&
|
||||
@@ -549,7 +563,7 @@ mem_malloc(mem_size_t size)
|
||||
*/
|
||||
ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
|
||||
/* create mem2 struct */
|
||||
mem2 = (struct mem *)&ram[ptr2];
|
||||
mem2 = (struct mem *)(void *)&ram[ptr2];
|
||||
mem2->used = 0;
|
||||
mem2->next = mem->next;
|
||||
mem2->prev = ptr;
|
||||
@@ -558,7 +572,7 @@ mem_malloc(mem_size_t size)
|
||||
mem->used = 1;
|
||||
|
||||
if (mem2->next != MEM_SIZE_ALIGNED) {
|
||||
((struct mem *)&ram[mem2->next])->prev = ptr2;
|
||||
((struct mem *)(void *)&ram[mem2->next])->prev = ptr2;
|
||||
}
|
||||
MEM_STATS_INC_USED(used, (size + SIZEOF_STRUCT_MEM));
|
||||
} else {
|
||||
@@ -570,21 +584,33 @@ mem_malloc(mem_size_t size)
|
||||
* will always be used at this point!
|
||||
*/
|
||||
mem->used = 1;
|
||||
MEM_STATS_INC_USED(used, mem->next - ((u8_t *)mem - ram));
|
||||
MEM_STATS_INC_USED(used, mem->next - (mem_size_t)((u8_t *)mem - ram));
|
||||
}
|
||||
|
||||
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
|
||||
mem_malloc_adjust_lfree:
|
||||
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
|
||||
if (mem == lfree) {
|
||||
struct mem *cur = lfree;
|
||||
/* Find next free block after mem and update lowest free pointer */
|
||||
while (lfree->used && lfree != ram_end) {
|
||||
while (cur->used && cur != ram_end) {
|
||||
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
|
||||
mem_free_count = 0;
|
||||
LWIP_MEM_ALLOC_UNPROTECT();
|
||||
/* prevent high interrupt latency... */
|
||||
LWIP_MEM_ALLOC_PROTECT();
|
||||
lfree = (struct mem *)&ram[lfree->next];
|
||||
if (mem_free_count != 0) {
|
||||
/* If mem_free or mem_trim have run, we have to restart since they
|
||||
could have altered our current struct mem or lfree. */
|
||||
goto mem_malloc_adjust_lfree;
|
||||
}
|
||||
#endif /* LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT */
|
||||
cur = (struct mem *)(void *)&ram[cur->next];
|
||||
}
|
||||
lfree = cur;
|
||||
LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used)));
|
||||
}
|
||||
LWIP_MEM_ALLOC_UNPROTECT();
|
||||
sys_sem_signal(mem_sem);
|
||||
sys_mutex_unlock(&mem_mutex);
|
||||
LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
|
||||
(mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
|
||||
LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
|
||||
@@ -602,7 +628,7 @@ mem_malloc(mem_size_t size)
|
||||
LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));
|
||||
MEM_STATS_INC(err);
|
||||
LWIP_MEM_ALLOC_UNPROTECT();
|
||||
sys_sem_signal(mem_sem);
|
||||
sys_mutex_unlock(&mem_mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
138
src/core/memp.c
138
src/core/memp.c
@@ -44,15 +44,20 @@
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/raw.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/tcp_impl.h"
|
||||
#include "lwip/igmp.h"
|
||||
#include "lwip/api.h"
|
||||
#include "lwip/api_msg.h"
|
||||
#include "lwip/tcpip.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/timers.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "netif/etharp.h"
|
||||
#include "lwip/ip_frag.h"
|
||||
#include "lwip/snmp_structs.h"
|
||||
#include "lwip/snmp_msg.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "netif/ppp_oe.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -142,27 +147,49 @@ static const char *memp_desc[MEMP_MAX] = {
|
||||
};
|
||||
#endif /* LWIP_DEBUG */
|
||||
|
||||
/** This is the actual memory used by the pools. */
|
||||
#if MEMP_SEPARATE_POOLS
|
||||
|
||||
/** This creates each memory pool. These are named memp_memory_XXX_base (where
|
||||
* XXX is the name of the pool defined in memp_std.h).
|
||||
* To relocate a pool, declare it as extern in cc.h. Example for GCC:
|
||||
* extern u8_t __attribute__((section(".onchip_mem"))) memp_memory_UDP_PCB_base[];
|
||||
*/
|
||||
#define LWIP_MEMPOOL(name,num,size,desc) u8_t memp_memory_ ## name ## _base \
|
||||
[((num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size)))];
|
||||
#include "lwip/memp_std.h"
|
||||
|
||||
/** This array holds the base of each memory pool. */
|
||||
static u8_t *const memp_bases[] = {
|
||||
#define LWIP_MEMPOOL(name,num,size,desc) memp_memory_ ## name ## _base,
|
||||
#include "lwip/memp_std.h"
|
||||
};
|
||||
|
||||
#else /* MEMP_SEPARATE_POOLS */
|
||||
|
||||
/** This is the actual memory used by the pools (all pools in one big block). */
|
||||
static u8_t memp_memory[MEM_ALIGNMENT - 1
|
||||
#define LWIP_MEMPOOL(name,num,size,desc) + ( (num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size) ) )
|
||||
#include "lwip/memp_std.h"
|
||||
];
|
||||
|
||||
#endif /* MEMP_SEPARATE_POOLS */
|
||||
|
||||
#if MEMP_SANITY_CHECK
|
||||
/**
|
||||
* Check that memp-lists don't form a circle
|
||||
* Check that memp-lists don't form a circle, using "Floyd's cycle-finding algorithm".
|
||||
*/
|
||||
static int
|
||||
memp_sanity(void)
|
||||
{
|
||||
s16_t i, c;
|
||||
struct memp *m, *n;
|
||||
s16_t i;
|
||||
struct memp *t, *h;
|
||||
|
||||
for (i = 0; i < MEMP_MAX; i++) {
|
||||
for (m = memp_tab[i]; m != NULL; m = m->next) {
|
||||
c = 1;
|
||||
for (n = memp_tab[i]; n != NULL; n = n->next) {
|
||||
if (n == m && --c < 0) {
|
||||
t = memp_tab[i];
|
||||
if(t != NULL) {
|
||||
for (h = t->next; (t != NULL) && (h != NULL); t = t->next,
|
||||
h = (((h->next != NULL) && (h->next->next != NULL)) ? h->next->next : NULL)) {
|
||||
if (t == h) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -172,15 +199,55 @@ memp_sanity(void)
|
||||
}
|
||||
#endif /* MEMP_SANITY_CHECK*/
|
||||
#if MEMP_OVERFLOW_CHECK
|
||||
#if defined(LWIP_DEBUG) && MEMP_STATS
|
||||
static const char * memp_overflow_names[] = {
|
||||
#define LWIP_MEMPOOL(name,num,size,desc) "/"desc,
|
||||
#include "lwip/memp_std.h"
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Check if a memp element was victim of an overflow
|
||||
* (e.g. the restricted area after it has been altered)
|
||||
*
|
||||
* @param p the memp element to check
|
||||
* @param memp_size the element size of the pool p comes from
|
||||
* @param memp_type the pool p comes from
|
||||
*/
|
||||
static void
|
||||
memp_overflow_check_element(struct memp *p, u16_t memp_size)
|
||||
memp_overflow_check_element_overflow(struct memp *p, u16_t memp_type)
|
||||
{
|
||||
u16_t k;
|
||||
u8_t *m;
|
||||
#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0
|
||||
m = (u8_t*)p + MEMP_SIZE + memp_sizes[memp_type];
|
||||
for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) {
|
||||
if (m[k] != 0xcd) {
|
||||
char errstr[128] = "detected memp overflow in pool ";
|
||||
char digit[] = "0";
|
||||
if(memp_type >= 10) {
|
||||
digit[0] = '0' + (memp_type/10);
|
||||
strcat(errstr, digit);
|
||||
}
|
||||
digit[0] = '0' + (memp_type%10);
|
||||
strcat(errstr, digit);
|
||||
#if defined(LWIP_DEBUG) && MEMP_STATS
|
||||
strcat(errstr, memp_overflow_names[memp_type]);
|
||||
#endif
|
||||
LWIP_ASSERT(errstr, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a memp element was victim of an underflow
|
||||
* (e.g. the restricted area before it has been altered)
|
||||
*
|
||||
* @param p the memp element to check
|
||||
* @param memp_type the pool p comes from
|
||||
*/
|
||||
static void
|
||||
memp_overflow_check_element_underflow(struct memp *p, u16_t memp_type)
|
||||
{
|
||||
u16_t k;
|
||||
u8_t *m;
|
||||
@@ -188,15 +255,18 @@ memp_overflow_check_element(struct memp *p, u16_t memp_size)
|
||||
m = (u8_t*)p + MEMP_SIZE - MEMP_SANITY_REGION_BEFORE_ALIGNED;
|
||||
for (k = 0; k < MEMP_SANITY_REGION_BEFORE_ALIGNED; k++) {
|
||||
if (m[k] != 0xcd) {
|
||||
LWIP_ASSERT("detected memp underflow!", 0);
|
||||
}
|
||||
}
|
||||
char errstr[128] = "detected memp underflow in pool ";
|
||||
char digit[] = "0";
|
||||
if(memp_type >= 10) {
|
||||
digit[0] = '0' + (memp_type/10);
|
||||
strcat(errstr, digit);
|
||||
}
|
||||
digit[0] = '0' + (memp_type%10);
|
||||
strcat(errstr, digit);
|
||||
#if defined(LWIP_DEBUG) && MEMP_STATS
|
||||
strcat(errstr, memp_overflow_names[memp_type]);
|
||||
#endif
|
||||
#if MEMP_SANITY_REGION_AFTER_ALIGNED > 0
|
||||
m = (u8_t*)p + MEMP_SIZE + memp_size;
|
||||
for (k = 0; k < MEMP_SANITY_REGION_AFTER_ALIGNED; k++) {
|
||||
if (m[k] != 0xcd) {
|
||||
LWIP_ASSERT("detected memp overflow!", 0);
|
||||
LWIP_ASSERT(errstr, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -213,11 +283,19 @@ memp_overflow_check_all(void)
|
||||
u16_t i, j;
|
||||
struct memp *p;
|
||||
|
||||
p = LWIP_MEM_ALIGN(memp_memory);
|
||||
p = (struct memp *)LWIP_MEM_ALIGN(memp_memory);
|
||||
for (i = 0; i < MEMP_MAX; ++i) {
|
||||
p = p;
|
||||
for (j = 0; j < memp_num[i]; ++j) {
|
||||
memp_overflow_check_element(p, memp_sizes[i]);
|
||||
memp_overflow_check_element_overflow(p, i);
|
||||
p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED);
|
||||
}
|
||||
}
|
||||
p = (struct memp *)LWIP_MEM_ALIGN(memp_memory);
|
||||
for (i = 0; i < MEMP_MAX; ++i) {
|
||||
p = p;
|
||||
for (j = 0; j < memp_num[i]; ++j) {
|
||||
memp_overflow_check_element_underflow(p, i);
|
||||
p = (struct memp*)((u8_t*)p + MEMP_SIZE + memp_sizes[i] + MEMP_SANITY_REGION_AFTER_ALIGNED);
|
||||
}
|
||||
}
|
||||
@@ -233,7 +311,7 @@ memp_overflow_init(void)
|
||||
struct memp *p;
|
||||
u8_t *m;
|
||||
|
||||
p = LWIP_MEM_ALIGN(memp_memory);
|
||||
p = (struct memp *)LWIP_MEM_ALIGN(memp_memory);
|
||||
for (i = 0; i < MEMP_MAX; ++i) {
|
||||
p = p;
|
||||
for (j = 0; j < memp_num[i]; ++j) {
|
||||
@@ -269,15 +347,20 @@ memp_init(void)
|
||||
MEMP_STATS_AVAIL(avail, i, memp_num[i]);
|
||||
}
|
||||
|
||||
memp = LWIP_MEM_ALIGN(memp_memory);
|
||||
#if !MEMP_SEPARATE_POOLS
|
||||
memp = (struct memp *)LWIP_MEM_ALIGN(memp_memory);
|
||||
#endif /* !MEMP_SEPARATE_POOLS */
|
||||
/* for every pool: */
|
||||
for (i = 0; i < MEMP_MAX; ++i) {
|
||||
memp_tab[i] = NULL;
|
||||
#if MEMP_SEPARATE_POOLS
|
||||
memp = (struct memp*)memp_bases[i];
|
||||
#endif /* MEMP_SEPARATE_POOLS */
|
||||
/* create a linked list of memp elements */
|
||||
for (j = 0; j < memp_num[i]; ++j) {
|
||||
memp->next = memp_tab[i];
|
||||
memp_tab[i] = memp;
|
||||
memp = (struct memp *)((u8_t *)memp + MEMP_SIZE + memp_sizes[i]
|
||||
memp = (struct memp *)(void *)((u8_t *)memp + MEMP_SIZE + memp_sizes[i]
|
||||
#if MEMP_OVERFLOW_CHECK
|
||||
+ MEMP_SANITY_REGION_AFTER_ALIGNED
|
||||
#endif
|
||||
@@ -331,7 +414,7 @@ memp_malloc_fn(memp_t type, const char* file, const int line)
|
||||
MEMP_STATS_INC_USED(used, type);
|
||||
LWIP_ASSERT("memp_malloc: memp properly aligned",
|
||||
((mem_ptr_t)memp % MEM_ALIGNMENT) == 0);
|
||||
memp = (struct memp*)((u8_t*)memp + MEMP_SIZE);
|
||||
memp = (struct memp*)(void *)((u8_t*)memp + MEMP_SIZE);
|
||||
} else {
|
||||
LWIP_DEBUGF(MEMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("memp_malloc: out of memory in pool %s\n", memp_desc[type]));
|
||||
MEMP_STATS_INC(err, type);
|
||||
@@ -360,14 +443,15 @@ memp_free(memp_t type, void *mem)
|
||||
LWIP_ASSERT("memp_free: mem properly aligned",
|
||||
((mem_ptr_t)mem % MEM_ALIGNMENT) == 0);
|
||||
|
||||
memp = (struct memp *)((u8_t*)mem - MEMP_SIZE);
|
||||
memp = (struct memp *)(void *)((u8_t*)mem - MEMP_SIZE);
|
||||
|
||||
SYS_ARCH_PROTECT(old_level);
|
||||
#if MEMP_OVERFLOW_CHECK
|
||||
#if MEMP_OVERFLOW_CHECK >= 2
|
||||
memp_overflow_check_all();
|
||||
#else
|
||||
memp_overflow_check_element(memp, memp_sizes[type]);
|
||||
memp_overflow_check_element_overflow(memp, type);
|
||||
memp_overflow_check_element_underflow(memp, type);
|
||||
#endif /* MEMP_OVERFLOW_CHECK >= 2 */
|
||||
#endif /* MEMP_OVERFLOW_CHECK */
|
||||
|
||||
|
||||
337
src/core/netif.c
337
src/core/netif.c
@@ -41,10 +41,11 @@
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/tcp_impl.h"
|
||||
#include "lwip/snmp.h"
|
||||
#include "lwip/igmp.h"
|
||||
#include "netif/etharp.h"
|
||||
#include "lwip/stats.h"
|
||||
#if ENABLE_LOOPBACK
|
||||
#include "lwip/sys.h"
|
||||
#if LWIP_NETIF_LOOPBACK_MULTITHREADING
|
||||
@@ -60,20 +61,66 @@
|
||||
#endif /* LWIP_DHCP */
|
||||
|
||||
#if LWIP_NETIF_STATUS_CALLBACK
|
||||
#define NETIF_STATUS_CALLBACK(n) { if (n->status_callback) (n->status_callback)(n); }
|
||||
#define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0)
|
||||
#else
|
||||
#define NETIF_STATUS_CALLBACK(n) { /* NOP */ }
|
||||
#define NETIF_STATUS_CALLBACK(n)
|
||||
#endif /* LWIP_NETIF_STATUS_CALLBACK */
|
||||
|
||||
#if LWIP_NETIF_LINK_CALLBACK
|
||||
#define NETIF_LINK_CALLBACK(n) { if (n->link_callback) (n->link_callback)(n); }
|
||||
#define NETIF_LINK_CALLBACK(n) do{ if (n->link_callback) { (n->link_callback)(n); }}while(0)
|
||||
#else
|
||||
#define NETIF_LINK_CALLBACK(n) { /* NOP */ }
|
||||
#define NETIF_LINK_CALLBACK(n)
|
||||
#endif /* LWIP_NETIF_LINK_CALLBACK */
|
||||
|
||||
struct netif *netif_list;
|
||||
struct netif *netif_default;
|
||||
|
||||
static u8_t netif_num;
|
||||
|
||||
#if LWIP_HAVE_LOOPIF
|
||||
static struct netif loop_netif;
|
||||
|
||||
/**
|
||||
* Initialize a lwip network interface structure for a loopback interface
|
||||
*
|
||||
* @param netif the lwip network interface structure for this loopif
|
||||
* @return ERR_OK if the loopif is initialized
|
||||
* ERR_MEM if private data couldn't be allocated
|
||||
*/
|
||||
static err_t
|
||||
netif_loopif_init(struct netif *netif)
|
||||
{
|
||||
/* initialize the snmp variables and counters inside the struct netif
|
||||
* ifSpeed: no assumption can be made!
|
||||
*/
|
||||
NETIF_INIT_SNMP(netif, snmp_ifType_softwareLoopback, 0);
|
||||
|
||||
netif->name[0] = 'l';
|
||||
netif->name[1] = 'o';
|
||||
netif->output = netif_loop_output;
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif /* LWIP_HAVE_LOOPIF */
|
||||
|
||||
void
|
||||
netif_init(void)
|
||||
{
|
||||
#if LWIP_HAVE_LOOPIF
|
||||
ip_addr_t loop_ipaddr, loop_netmask, loop_gw;
|
||||
IP4_ADDR(&loop_gw, 127,0,0,1);
|
||||
IP4_ADDR(&loop_ipaddr, 127,0,0,1);
|
||||
IP4_ADDR(&loop_netmask, 255,0,0,0);
|
||||
|
||||
#if NO_SYS
|
||||
netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, netif_loopif_init, ip_input);
|
||||
#else /* NO_SYS */
|
||||
netif_add(&loop_netif, &loop_ipaddr, &loop_netmask, &loop_gw, NULL, netif_loopif_init, tcpip_input);
|
||||
#endif /* NO_SYS */
|
||||
netif_set_up(&loop_netif);
|
||||
|
||||
#endif /* LWIP_HAVE_LOOPIF */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a network interface to the list of lwIP netifs.
|
||||
*
|
||||
@@ -89,18 +136,16 @@ struct netif *netif_default;
|
||||
* @return netif, or NULL if failed.
|
||||
*/
|
||||
struct netif *
|
||||
netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
|
||||
struct ip_addr *gw,
|
||||
void *state,
|
||||
err_t (* init)(struct netif *netif),
|
||||
err_t (* input)(struct pbuf *p, struct netif *netif))
|
||||
netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
|
||||
ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input)
|
||||
{
|
||||
static u8_t netifnum = 0;
|
||||
|
||||
LWIP_ASSERT("No init function given", init != NULL);
|
||||
|
||||
/* reset new interface configuration state */
|
||||
netif->ip_addr.addr = 0;
|
||||
netif->netmask.addr = 0;
|
||||
netif->gw.addr = 0;
|
||||
ip_addr_set_zero(&netif->ip_addr);
|
||||
ip_addr_set_zero(&netif->netmask);
|
||||
ip_addr_set_zero(&netif->gw);
|
||||
netif->flags = 0;
|
||||
#if LWIP_DHCP
|
||||
/* netif not under DHCP control by default */
|
||||
@@ -126,11 +171,9 @@ netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
|
||||
|
||||
/* remember netif specific state information data */
|
||||
netif->state = state;
|
||||
netif->num = netifnum++;
|
||||
netif->num = netif_num++;
|
||||
netif->input = input;
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
netif->addr_hint = NULL;
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
NETIF_SET_HWADDRHINT(netif, NULL);
|
||||
#if ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS
|
||||
netif->loop_cnt_current = 0;
|
||||
#endif /* ENABLE_LOOPBACK && LWIP_LOOPBACK_MAX_PBUFS */
|
||||
@@ -150,7 +193,7 @@ netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
|
||||
#if LWIP_IGMP
|
||||
/* start IGMP processing */
|
||||
if (netif->flags & NETIF_FLAG_IGMP) {
|
||||
igmp_start( netif);
|
||||
igmp_start(netif);
|
||||
}
|
||||
#endif /* LWIP_IGMP */
|
||||
|
||||
@@ -175,8 +218,8 @@ netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
|
||||
* @param gw the new default gateway
|
||||
*/
|
||||
void
|
||||
netif_set_addr(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
|
||||
struct ip_addr *gw)
|
||||
netif_set_addr(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
|
||||
ip_addr_t *gw)
|
||||
{
|
||||
netif_set_ipaddr(netif, ipaddr);
|
||||
netif_set_netmask(netif, netmask);
|
||||
@@ -188,41 +231,52 @@ netif_set_addr(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netm
|
||||
*
|
||||
* @param netif the network interface to remove
|
||||
*/
|
||||
void netif_remove(struct netif * netif)
|
||||
void
|
||||
netif_remove(struct netif *netif)
|
||||
{
|
||||
if ( netif == NULL ) return;
|
||||
if (netif == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if LWIP_IGMP
|
||||
/* stop IGMP processing */
|
||||
if (netif->flags & NETIF_FLAG_IGMP) {
|
||||
igmp_stop( netif);
|
||||
igmp_stop(netif);
|
||||
}
|
||||
#endif /* LWIP_IGMP */
|
||||
if (netif_is_up(netif)) {
|
||||
/* set netif down before removing (call callback function) */
|
||||
netif_set_down(netif);
|
||||
}
|
||||
|
||||
snmp_delete_ipaddridx_tree(netif);
|
||||
|
||||
/* is it the first netif? */
|
||||
if (netif_list == netif) {
|
||||
netif_list = netif->next;
|
||||
snmp_dec_iflist();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* look for netif further down the list */
|
||||
struct netif * tmpNetif;
|
||||
for (tmpNetif = netif_list; tmpNetif != NULL; tmpNetif = tmpNetif->next) {
|
||||
if (tmpNetif->next == netif) {
|
||||
tmpNetif->next = netif->next;
|
||||
snmp_dec_iflist();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tmpNetif == NULL)
|
||||
return; /* we didn't find any netif today */
|
||||
}
|
||||
snmp_dec_iflist();
|
||||
/* this netif is default? */
|
||||
if (netif_default == netif)
|
||||
if (netif_default == netif) {
|
||||
/* reset default netif */
|
||||
netif_set_default(NULL);
|
||||
}
|
||||
#if LWIP_NETIF_REMOVE_CALLBACK
|
||||
if (netif->remove_callback) {
|
||||
netif->remove_callback(netif);
|
||||
}
|
||||
#endif /* LWIP_NETIF_REMOVE_CALLBACK */
|
||||
LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") );
|
||||
}
|
||||
|
||||
@@ -266,7 +320,7 @@ netif_find(char *name)
|
||||
* default gateway
|
||||
*/
|
||||
void
|
||||
netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
|
||||
netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr)
|
||||
{
|
||||
/* TODO: Handling of obsolete pcbs */
|
||||
/* See: http://mail.gnu.org/archive/html/lwip-users/2003-03/msg00118.html */
|
||||
@@ -275,14 +329,18 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
|
||||
struct tcp_pcb_listen *lpcb;
|
||||
|
||||
/* address is actually being changed? */
|
||||
if ((ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0)
|
||||
{
|
||||
if (ipaddr && (ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0) {
|
||||
/* extern struct tcp_pcb *tcp_active_pcbs; defined by tcp.h */
|
||||
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: netif address being changed\n"));
|
||||
pcb = tcp_active_pcbs;
|
||||
while (pcb != NULL) {
|
||||
/* PCB bound to current local interface address? */
|
||||
if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) {
|
||||
if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))
|
||||
#if LWIP_AUTOIP
|
||||
/* connections to link-local addresses must persist (RFC3927 ch. 1.9) */
|
||||
&& !ip_addr_islinklocal(&(pcb->local_ip))
|
||||
#endif /* LWIP_AUTOIP */
|
||||
) {
|
||||
/* this connection must be aborted */
|
||||
struct tcp_pcb *next = pcb->next;
|
||||
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb));
|
||||
@@ -312,10 +370,10 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
|
||||
|
||||
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
netif->name[0], netif->name[1],
|
||||
ip4_addr1(&netif->ip_addr),
|
||||
ip4_addr2(&netif->ip_addr),
|
||||
ip4_addr3(&netif->ip_addr),
|
||||
ip4_addr4(&netif->ip_addr)));
|
||||
ip4_addr1_16(&netif->ip_addr),
|
||||
ip4_addr2_16(&netif->ip_addr),
|
||||
ip4_addr3_16(&netif->ip_addr),
|
||||
ip4_addr4_16(&netif->ip_addr)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -327,15 +385,15 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
|
||||
* @note call netif_set_addr() if you also want to change ip address and netmask
|
||||
*/
|
||||
void
|
||||
netif_set_gw(struct netif *netif, struct ip_addr *gw)
|
||||
netif_set_gw(struct netif *netif, ip_addr_t *gw)
|
||||
{
|
||||
ip_addr_set(&(netif->gw), gw);
|
||||
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
netif->name[0], netif->name[1],
|
||||
ip4_addr1(&netif->gw),
|
||||
ip4_addr2(&netif->gw),
|
||||
ip4_addr3(&netif->gw),
|
||||
ip4_addr4(&netif->gw)));
|
||||
ip4_addr1_16(&netif->gw),
|
||||
ip4_addr2_16(&netif->gw),
|
||||
ip4_addr3_16(&netif->gw),
|
||||
ip4_addr4_16(&netif->gw)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -348,7 +406,7 @@ netif_set_gw(struct netif *netif, struct ip_addr *gw)
|
||||
* default gateway
|
||||
*/
|
||||
void
|
||||
netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
|
||||
netif_set_netmask(struct netif *netif, ip_addr_t *netmask)
|
||||
{
|
||||
snmp_delete_iprteidx_tree(0, netif);
|
||||
/* set new netmask to netif */
|
||||
@@ -356,10 +414,10 @@ netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
|
||||
snmp_insert_iprteidx_tree(0, netif);
|
||||
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
netif->name[0], netif->name[1],
|
||||
ip4_addr1(&netif->netmask),
|
||||
ip4_addr2(&netif->netmask),
|
||||
ip4_addr3(&netif->netmask),
|
||||
ip4_addr4(&netif->netmask)));
|
||||
ip4_addr1_16(&netif->netmask),
|
||||
ip4_addr2_16(&netif->netmask),
|
||||
ip4_addr3_16(&netif->netmask),
|
||||
ip4_addr4_16(&netif->netmask)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -371,13 +429,10 @@ netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
|
||||
void
|
||||
netif_set_default(struct netif *netif)
|
||||
{
|
||||
if (netif == NULL)
|
||||
{
|
||||
if (netif == NULL) {
|
||||
/* remove default route */
|
||||
snmp_delete_iprteidx_tree(1, netif);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/* install default route */
|
||||
snmp_insert_iprteidx_tree(1, netif);
|
||||
}
|
||||
@@ -397,29 +452,30 @@ netif_set_default(struct netif *netif)
|
||||
*/
|
||||
void netif_set_up(struct netif *netif)
|
||||
{
|
||||
if ( !(netif->flags & NETIF_FLAG_UP )) {
|
||||
if (!(netif->flags & NETIF_FLAG_UP)) {
|
||||
netif->flags |= NETIF_FLAG_UP;
|
||||
|
||||
#if LWIP_SNMP
|
||||
snmp_get_sysuptime(&netif->ts);
|
||||
#endif /* LWIP_SNMP */
|
||||
|
||||
NETIF_LINK_CALLBACK(netif);
|
||||
NETIF_STATUS_CALLBACK(netif);
|
||||
|
||||
if (netif->flags & NETIF_FLAG_LINK_UP) {
|
||||
#if LWIP_ARP
|
||||
/* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */
|
||||
if (netif->flags & NETIF_FLAG_ETHARP) {
|
||||
etharp_gratuitous(netif);
|
||||
}
|
||||
/* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */
|
||||
if (netif->flags & (NETIF_FLAG_ETHARP)) {
|
||||
etharp_gratuitous(netif);
|
||||
}
|
||||
#endif /* LWIP_ARP */
|
||||
|
||||
#if LWIP_IGMP
|
||||
/* resend IGMP memberships */
|
||||
if (netif->flags & NETIF_FLAG_IGMP) {
|
||||
igmp_report_groups( netif);
|
||||
}
|
||||
/* resend IGMP memberships */
|
||||
if (netif->flags & NETIF_FLAG_IGMP) {
|
||||
igmp_report_groups( netif);
|
||||
}
|
||||
#endif /* LWIP_IGMP */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -433,73 +489,83 @@ void netif_set_up(struct netif *netif)
|
||||
*/
|
||||
void netif_set_down(struct netif *netif)
|
||||
{
|
||||
if ( netif->flags & NETIF_FLAG_UP )
|
||||
{
|
||||
netif->flags &= ~NETIF_FLAG_UP;
|
||||
if (netif->flags & NETIF_FLAG_UP) {
|
||||
netif->flags &= ~NETIF_FLAG_UP;
|
||||
#if LWIP_SNMP
|
||||
snmp_get_sysuptime(&netif->ts);
|
||||
snmp_get_sysuptime(&netif->ts);
|
||||
#endif
|
||||
|
||||
NETIF_LINK_CALLBACK(netif);
|
||||
NETIF_STATUS_CALLBACK(netif);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask if an interface is up
|
||||
*/
|
||||
u8_t netif_is_up(struct netif *netif)
|
||||
{
|
||||
return (netif->flags & NETIF_FLAG_UP)?1:0;
|
||||
#if LWIP_ARP
|
||||
if (netif->flags & NETIF_FLAG_ETHARP) {
|
||||
etharp_cleanup_netif(netif);
|
||||
}
|
||||
#endif /* LWIP_ARP */
|
||||
NETIF_STATUS_CALLBACK(netif);
|
||||
}
|
||||
}
|
||||
|
||||
#if LWIP_NETIF_STATUS_CALLBACK
|
||||
/**
|
||||
* Set callback to be called when interface is brought up/down
|
||||
*/
|
||||
void netif_set_status_callback(struct netif *netif, void (* status_callback)(struct netif *netif ))
|
||||
void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback)
|
||||
{
|
||||
if ( netif )
|
||||
netif->status_callback = status_callback;
|
||||
if (netif) {
|
||||
netif->status_callback = status_callback;
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_NETIF_STATUS_CALLBACK */
|
||||
|
||||
#if LWIP_NETIF_LINK_CALLBACK
|
||||
#if LWIP_NETIF_REMOVE_CALLBACK
|
||||
/**
|
||||
* Set callback to be called when the interface has been removed
|
||||
*/
|
||||
void
|
||||
netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback)
|
||||
{
|
||||
if (netif) {
|
||||
netif->remove_callback = remove_callback;
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_NETIF_REMOVE_CALLBACK */
|
||||
|
||||
/**
|
||||
* Called by a driver when its link goes up
|
||||
*/
|
||||
void netif_set_link_up(struct netif *netif )
|
||||
{
|
||||
netif->flags |= NETIF_FLAG_LINK_UP;
|
||||
if (!(netif->flags & NETIF_FLAG_LINK_UP)) {
|
||||
netif->flags |= NETIF_FLAG_LINK_UP;
|
||||
|
||||
#if LWIP_DHCP
|
||||
if (netif->dhcp) {
|
||||
dhcp_network_changed(netif);
|
||||
}
|
||||
if (netif->dhcp) {
|
||||
dhcp_network_changed(netif);
|
||||
}
|
||||
#endif /* LWIP_DHCP */
|
||||
|
||||
#if LWIP_AUTOIP
|
||||
if (netif->autoip) {
|
||||
autoip_network_changed(netif);
|
||||
}
|
||||
if (netif->autoip) {
|
||||
autoip_network_changed(netif);
|
||||
}
|
||||
#endif /* LWIP_AUTOIP */
|
||||
|
||||
if (netif->flags & NETIF_FLAG_UP) {
|
||||
if (netif->flags & NETIF_FLAG_UP) {
|
||||
#if LWIP_ARP
|
||||
/* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */
|
||||
if (netif->flags & NETIF_FLAG_ETHARP) {
|
||||
etharp_gratuitous(netif);
|
||||
}
|
||||
/* For Ethernet network interfaces, we would like to send a "gratuitous ARP" */
|
||||
if (netif->flags & NETIF_FLAG_ETHARP) {
|
||||
etharp_gratuitous(netif);
|
||||
}
|
||||
#endif /* LWIP_ARP */
|
||||
|
||||
#if LWIP_IGMP
|
||||
/* resend IGMP memberships */
|
||||
if (netif->flags & NETIF_FLAG_IGMP) {
|
||||
igmp_report_groups( netif);
|
||||
}
|
||||
/* resend IGMP memberships */
|
||||
if (netif->flags & NETIF_FLAG_IGMP) {
|
||||
igmp_report_groups( netif);
|
||||
}
|
||||
#endif /* LWIP_IGMP */
|
||||
}
|
||||
NETIF_LINK_CALLBACK(netif);
|
||||
}
|
||||
NETIF_LINK_CALLBACK(netif);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -507,22 +573,17 @@ void netif_set_link_up(struct netif *netif )
|
||||
*/
|
||||
void netif_set_link_down(struct netif *netif )
|
||||
{
|
||||
netif->flags &= ~NETIF_FLAG_LINK_UP;
|
||||
NETIF_LINK_CALLBACK(netif);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask if a link is up
|
||||
*/
|
||||
u8_t netif_is_link_up(struct netif *netif)
|
||||
{
|
||||
return (netif->flags & NETIF_FLAG_LINK_UP) ? 1 : 0;
|
||||
if (netif->flags & NETIF_FLAG_LINK_UP) {
|
||||
netif->flags &= ~NETIF_FLAG_LINK_UP;
|
||||
NETIF_LINK_CALLBACK(netif);
|
||||
}
|
||||
}
|
||||
|
||||
#if LWIP_NETIF_LINK_CALLBACK
|
||||
/**
|
||||
* Set callback to be called when link is brought up/down
|
||||
*/
|
||||
void netif_set_link_callback(struct netif *netif, void (* link_callback)(struct netif *netif ))
|
||||
void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback)
|
||||
{
|
||||
if (netif) {
|
||||
netif->link_callback = link_callback;
|
||||
@@ -547,7 +608,7 @@ void netif_set_link_callback(struct netif *netif, void (* link_callback)(struct
|
||||
*/
|
||||
err_t
|
||||
netif_loop_output(struct netif *netif, struct pbuf *p,
|
||||
struct ip_addr *ipaddr)
|
||||
ip_addr_t *ipaddr)
|
||||
{
|
||||
struct pbuf *r;
|
||||
err_t err;
|
||||
@@ -555,22 +616,36 @@ netif_loop_output(struct netif *netif, struct pbuf *p,
|
||||
#if LWIP_LOOPBACK_MAX_PBUFS
|
||||
u8_t clen = 0;
|
||||
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
|
||||
/* If we have a loopif, SNMP counters are adjusted for it,
|
||||
* if not they are adjusted for 'netif'. */
|
||||
#if LWIP_SNMP
|
||||
#if LWIP_HAVE_LOOPIF
|
||||
struct netif *stats_if = &loop_netif;
|
||||
#else /* LWIP_HAVE_LOOPIF */
|
||||
struct netif *stats_if = netif;
|
||||
#endif /* LWIP_HAVE_LOOPIF */
|
||||
#endif /* LWIP_SNMP */
|
||||
SYS_ARCH_DECL_PROTECT(lev);
|
||||
LWIP_UNUSED_ARG(ipaddr);
|
||||
|
||||
/* Allocate a new pbuf */
|
||||
r = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM);
|
||||
if (r == NULL) {
|
||||
LINK_STATS_INC(link.memerr);
|
||||
LINK_STATS_INC(link.drop);
|
||||
snmp_inc_ifoutdiscards(stats_if);
|
||||
return ERR_MEM;
|
||||
}
|
||||
#if LWIP_LOOPBACK_MAX_PBUFS
|
||||
clen = pbuf_clen(r);
|
||||
/* check for overflow or too many pbuf on queue */
|
||||
if(((netif->loop_cnt_current + clen) < netif->loop_cnt_current) ||
|
||||
((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) {
|
||||
pbuf_free(r);
|
||||
r = NULL;
|
||||
return ERR_MEM;
|
||||
((netif->loop_cnt_current + clen) > LWIP_LOOPBACK_MAX_PBUFS)) {
|
||||
pbuf_free(r);
|
||||
LINK_STATS_INC(link.memerr);
|
||||
LINK_STATS_INC(link.drop);
|
||||
snmp_inc_ifoutdiscards(stats_if);
|
||||
return ERR_MEM;
|
||||
}
|
||||
netif->loop_cnt_current += clen;
|
||||
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
|
||||
@@ -578,7 +653,9 @@ netif_loop_output(struct netif *netif, struct pbuf *p,
|
||||
/* Copy the whole pbuf queue p into the single pbuf r */
|
||||
if ((err = pbuf_copy(r, p)) != ERR_OK) {
|
||||
pbuf_free(r);
|
||||
r = NULL;
|
||||
LINK_STATS_INC(link.memerr);
|
||||
LINK_STATS_INC(link.drop);
|
||||
snmp_inc_ifoutdiscards(stats_if);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -599,9 +676,13 @@ netif_loop_output(struct netif *netif, struct pbuf *p,
|
||||
}
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
|
||||
LINK_STATS_INC(link.xmit);
|
||||
snmp_add_ifoutoctets(stats_if, p->tot_len);
|
||||
snmp_inc_ifoutucastpkts(stats_if);
|
||||
|
||||
#if LWIP_NETIF_LOOPBACK_MULTITHREADING
|
||||
/* For multithreading environment, schedule a call to netif_poll */
|
||||
tcpip_callback((void (*)(void *))(netif_poll), netif);
|
||||
tcpip_callback((tcpip_callback_fn)netif_poll, netif);
|
||||
#endif /* LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
||||
|
||||
return ERR_OK;
|
||||
@@ -617,13 +698,22 @@ void
|
||||
netif_poll(struct netif *netif)
|
||||
{
|
||||
struct pbuf *in;
|
||||
/* If we have a loopif, SNMP counters are adjusted for it,
|
||||
* if not they are adjusted for 'netif'. */
|
||||
#if LWIP_SNMP
|
||||
#if LWIP_HAVE_LOOPIF
|
||||
struct netif *stats_if = &loop_netif;
|
||||
#else /* LWIP_HAVE_LOOPIF */
|
||||
struct netif *stats_if = netif;
|
||||
#endif /* LWIP_HAVE_LOOPIF */
|
||||
#endif /* LWIP_SNMP */
|
||||
SYS_ARCH_DECL_PROTECT(lev);
|
||||
|
||||
do {
|
||||
/* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
|
||||
SYS_ARCH_PROTECT(lev);
|
||||
in = netif->loop_first;
|
||||
if(in != NULL) {
|
||||
if (in != NULL) {
|
||||
struct pbuf *in_end = in;
|
||||
#if LWIP_LOOPBACK_MAX_PBUFS
|
||||
u8_t clen = pbuf_clen(in);
|
||||
@@ -632,12 +722,12 @@ netif_poll(struct netif *netif)
|
||||
((netif->loop_cnt_current - clen) < netif->loop_cnt_current));
|
||||
netif->loop_cnt_current -= clen;
|
||||
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
|
||||
while(in_end->len != in_end->tot_len) {
|
||||
while (in_end->len != in_end->tot_len) {
|
||||
LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
|
||||
in_end = in_end->next;
|
||||
}
|
||||
/* 'in_end' now points to the last pbuf from 'in' */
|
||||
if(in_end == netif->loop_last) {
|
||||
if (in_end == netif->loop_last) {
|
||||
/* this was the last pbuf in the list */
|
||||
netif->loop_first = netif->loop_last = NULL;
|
||||
} else {
|
||||
@@ -650,16 +740,19 @@ netif_poll(struct netif *netif)
|
||||
}
|
||||
SYS_ARCH_UNPROTECT(lev);
|
||||
|
||||
if(in != NULL) {
|
||||
if (in != NULL) {
|
||||
LINK_STATS_INC(link.recv);
|
||||
snmp_add_ifinoctets(stats_if, in->tot_len);
|
||||
snmp_inc_ifinucastpkts(stats_if);
|
||||
/* loopback packets are always IP packets! */
|
||||
if(ip_input(in, netif) != ERR_OK) {
|
||||
if (ip_input(in, netif) != ERR_OK) {
|
||||
pbuf_free(in);
|
||||
}
|
||||
/* Don't reference the packet any more! */
|
||||
in = NULL;
|
||||
}
|
||||
/* go on while there is a packet on the list */
|
||||
} while(netif->loop_first != NULL);
|
||||
} while (netif->loop_first != NULL);
|
||||
}
|
||||
|
||||
#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
|
||||
|
||||
360
src/core/pbuf.c
360
src/core/pbuf.c
@@ -70,8 +70,11 @@
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "arch/perf.h"
|
||||
#if TCP_QUEUE_OOSEQ
|
||||
#include "lwip/tcp.h"
|
||||
#if LWIP_TCP && TCP_QUEUE_OOSEQ
|
||||
#include "lwip/tcp_impl.h"
|
||||
#endif
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
#include "lwip/inet_chksum.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
@@ -81,18 +84,25 @@
|
||||
aligned there. Therefore, PBUF_POOL_BUFSIZE_ALIGNED can be used here. */
|
||||
#define PBUF_POOL_BUFSIZE_ALIGNED LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE)
|
||||
|
||||
#if !TCP_QUEUE_OOSEQ || NO_SYS
|
||||
#if !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ
|
||||
#define PBUF_POOL_IS_EMPTY()
|
||||
#else /* !TCP_QUEUE_OOSEQ || NO_SYS */
|
||||
/** Define this to 0 to prevent freeing ooseq pbufs when the PBUF_POOL is empty */
|
||||
#ifndef PBUF_POOL_FREE_OOSEQ
|
||||
#define PBUF_POOL_FREE_OOSEQ 1
|
||||
#endif /* PBUF_POOL_FREE_OOSEQ */
|
||||
#else /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */
|
||||
|
||||
#if PBUF_POOL_FREE_OOSEQ
|
||||
#if !NO_SYS
|
||||
#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL
|
||||
#include "lwip/tcpip.h"
|
||||
#define PBUF_POOL_FREE_OOSEQ_QUEUE_CALL() do { \
|
||||
if(tcpip_callback_with_block(pbuf_free_ooseq_callback, NULL, 0) != ERR_OK) { \
|
||||
SYS_ARCH_PROTECT(old_level); \
|
||||
pbuf_free_ooseq_pending = 0; \
|
||||
SYS_ARCH_UNPROTECT(old_level); \
|
||||
} } while(0)
|
||||
#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */
|
||||
#endif /* !NO_SYS */
|
||||
|
||||
volatile u8_t pbuf_free_ooseq_pending;
|
||||
#define PBUF_POOL_IS_EMPTY() pbuf_pool_is_empty()
|
||||
static u8_t pbuf_free_ooseq_queued;
|
||||
|
||||
/**
|
||||
* Attempt to reclaim some memory from queued out-of-sequence TCP segments
|
||||
* if we run out of pool pbufs. It's better to give priority to new packets
|
||||
@@ -101,15 +111,17 @@ static u8_t pbuf_free_ooseq_queued;
|
||||
* This must be done in the correct thread context therefore this function
|
||||
* can only be used with NO_SYS=0 and through tcpip_callback.
|
||||
*/
|
||||
static void
|
||||
pbuf_free_ooseq(void* arg)
|
||||
#if !NO_SYS
|
||||
static
|
||||
#endif /* !NO_SYS */
|
||||
void
|
||||
pbuf_free_ooseq(void)
|
||||
{
|
||||
struct tcp_pcb* pcb;
|
||||
SYS_ARCH_DECL_PROTECT(old_level);
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
|
||||
SYS_ARCH_PROTECT(old_level);
|
||||
pbuf_free_ooseq_queued = 0;
|
||||
pbuf_free_ooseq_pending = 0;
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
|
||||
for (pcb = tcp_active_pcbs; NULL != pcb; pcb = pcb->next) {
|
||||
@@ -123,29 +135,42 @@ pbuf_free_ooseq(void* arg)
|
||||
}
|
||||
}
|
||||
|
||||
#if !NO_SYS
|
||||
/**
|
||||
* Just a callback function for tcpip_timeout() that calls pbuf_free_ooseq().
|
||||
*/
|
||||
static void
|
||||
pbuf_free_ooseq_callback(void *arg)
|
||||
{
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
pbuf_free_ooseq();
|
||||
}
|
||||
#endif /* !NO_SYS */
|
||||
|
||||
/** Queue a call to pbuf_free_ooseq if not already queued. */
|
||||
static void
|
||||
pbuf_pool_is_empty(void)
|
||||
{
|
||||
#ifndef PBUF_POOL_FREE_OOSEQ_QUEUE_CALL
|
||||
SYS_ARCH_DECL_PROTECT(old_level);
|
||||
SYS_ARCH_PROTECT(old_level);
|
||||
pbuf_free_ooseq_pending = 1;
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
#else /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */
|
||||
u8_t queued;
|
||||
SYS_ARCH_DECL_PROTECT(old_level);
|
||||
|
||||
SYS_ARCH_PROTECT(old_level);
|
||||
queued = pbuf_free_ooseq_queued;
|
||||
pbuf_free_ooseq_queued = 1;
|
||||
queued = pbuf_free_ooseq_pending;
|
||||
pbuf_free_ooseq_pending = 1;
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
|
||||
if(!queued) {
|
||||
/* queue a call to pbuf_free_ooseq if not already queued */
|
||||
if(tcpip_callback_with_block(pbuf_free_ooseq, NULL, 0) != ERR_OK) {
|
||||
SYS_ARCH_PROTECT(old_level);
|
||||
pbuf_free_ooseq_queued = 0;
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
}
|
||||
PBUF_POOL_FREE_OOSEQ_QUEUE_CALL();
|
||||
}
|
||||
#endif /* PBUF_POOL_FREE_OOSEQ_QUEUE_CALL */
|
||||
}
|
||||
#endif /* PBUF_POOL_FREE_OOSEQ */
|
||||
#endif /* !TCP_QUEUE_OOSEQ || NO_SYS */
|
||||
#endif /* !LWIP_TCP || !TCP_QUEUE_OOSEQ || !PBUF_POOL_FREE_OOSEQ */
|
||||
|
||||
/**
|
||||
* Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type).
|
||||
@@ -187,21 +212,21 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F")\n", length));
|
||||
|
||||
/* determine header offset */
|
||||
offset = 0;
|
||||
switch (layer) {
|
||||
case PBUF_TRANSPORT:
|
||||
/* add room for transport (often TCP) layer header */
|
||||
offset += PBUF_TRANSPORT_HLEN;
|
||||
/* FALLTHROUGH */
|
||||
offset = PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN;
|
||||
break;
|
||||
case PBUF_IP:
|
||||
/* add room for IP layer header */
|
||||
offset += PBUF_IP_HLEN;
|
||||
/* FALLTHROUGH */
|
||||
offset = PBUF_LINK_HLEN + PBUF_IP_HLEN;
|
||||
break;
|
||||
case PBUF_LINK:
|
||||
/* add room for link layer header */
|
||||
offset += PBUF_LINK_HLEN;
|
||||
offset = PBUF_LINK_HLEN;
|
||||
break;
|
||||
case PBUF_RAW:
|
||||
offset = 0;
|
||||
break;
|
||||
default:
|
||||
LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0);
|
||||
@@ -211,7 +236,7 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
|
||||
switch (type) {
|
||||
case PBUF_POOL:
|
||||
/* allocate head of pbuf chain into p */
|
||||
p = memp_malloc(MEMP_PBUF_POOL);
|
||||
p = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL);
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc: allocated pbuf %p\n", (void *)p));
|
||||
if (p == NULL) {
|
||||
PBUF_POOL_IS_EMPTY();
|
||||
@@ -244,7 +269,7 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
|
||||
rem_len = length - p->len;
|
||||
/* any remaining pbufs to be allocated? */
|
||||
while (rem_len > 0) {
|
||||
q = memp_malloc(MEMP_PBUF_POOL);
|
||||
q = (struct pbuf *)memp_malloc(MEMP_PBUF_POOL);
|
||||
if (q == NULL) {
|
||||
PBUF_POOL_IS_EMPTY();
|
||||
/* free chain so far allocated */
|
||||
@@ -298,7 +323,7 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
|
||||
/* pbuf references existing (externally allocated) RAM payload? */
|
||||
case PBUF_REF:
|
||||
/* only allocate memory for the pbuf structure */
|
||||
p = memp_malloc(MEMP_PBUF);
|
||||
p = (struct pbuf *)memp_malloc(MEMP_PBUF);
|
||||
if (p == NULL) {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n",
|
||||
@@ -323,6 +348,68 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
|
||||
return p;
|
||||
}
|
||||
|
||||
#if LWIP_SUPPORT_CUSTOM_PBUF
|
||||
/** Initialize a custom pbuf (already allocated).
|
||||
*
|
||||
* @param layer flag to define header size
|
||||
* @param length size of the pbuf's payload
|
||||
* @param type type of the pbuf (only used to treat the pbuf accordingly, as
|
||||
* this function allocates no memory)
|
||||
* @param p pointer to the custom pbuf to initialize (already allocated)
|
||||
* @param payload_mem pointer to the buffer that is used for payload and headers,
|
||||
* must be at least big enough to hold 'length' plus the header size,
|
||||
* may be NULL if set later.
|
||||
* ATTENTION: The caller is responsible for correct alignment of this buffer!!
|
||||
* @param payload_mem_len the size of the 'payload_mem' buffer, must be at least
|
||||
* big enough to hold 'length' plus the header size
|
||||
*/
|
||||
struct pbuf*
|
||||
pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type, struct pbuf_custom *p,
|
||||
void *payload_mem, u16_t payload_mem_len)
|
||||
{
|
||||
u16_t offset;
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloced_custom(length=%"U16_F")\n", length));
|
||||
|
||||
/* determine header offset */
|
||||
switch (l) {
|
||||
case PBUF_TRANSPORT:
|
||||
/* add room for transport (often TCP) layer header */
|
||||
offset = PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN;
|
||||
break;
|
||||
case PBUF_IP:
|
||||
/* add room for IP layer header */
|
||||
offset = PBUF_LINK_HLEN + PBUF_IP_HLEN;
|
||||
break;
|
||||
case PBUF_LINK:
|
||||
/* add room for link layer header */
|
||||
offset = PBUF_LINK_HLEN;
|
||||
break;
|
||||
case PBUF_RAW:
|
||||
offset = 0;
|
||||
break;
|
||||
default:
|
||||
LWIP_ASSERT("pbuf_alloced_custom: bad pbuf layer", 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (LWIP_MEM_ALIGN_SIZE(offset) + length > payload_mem_len) {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_LEVEL_WARNING, ("pbuf_alloced_custom(length=%"U16_F") buffer too short\n", length));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p->pbuf.next = NULL;
|
||||
if (payload_mem != NULL) {
|
||||
p->pbuf.payload = (u8_t *)payload_mem + LWIP_MEM_ALIGN_SIZE(offset);
|
||||
} else {
|
||||
p->pbuf.payload = NULL;
|
||||
}
|
||||
p->pbuf.flags = PBUF_FLAG_IS_CUSTOM;
|
||||
p->pbuf.len = p->pbuf.tot_len = length;
|
||||
p->pbuf.type = type;
|
||||
p->pbuf.ref = 1;
|
||||
return &p->pbuf;
|
||||
}
|
||||
#endif /* LWIP_SUPPORT_CUSTOM_PBUF */
|
||||
|
||||
/**
|
||||
* Shrink a pbuf chain to a desired length.
|
||||
@@ -383,8 +470,8 @@ pbuf_realloc(struct pbuf *p, u16_t new_len)
|
||||
/* (other types merely adjust their length fields */
|
||||
if ((q->type == PBUF_RAM) && (rem_len != q->len)) {
|
||||
/* reallocate and adjust the length of the pbuf that will be split */
|
||||
q = mem_realloc(q, (u8_t *)q->payload - (u8_t *)q + rem_len);
|
||||
LWIP_ASSERT("mem_realloc give q == NULL", q != NULL);
|
||||
q = (struct pbuf *)mem_trim(q, (u16_t)((u8_t *)q->payload - (u8_t *)q) + rem_len);
|
||||
LWIP_ASSERT("mem_trim returned q == NULL", q != NULL);
|
||||
}
|
||||
/* adjust length fields for new last pbuf */
|
||||
q->len = rem_len;
|
||||
@@ -428,8 +515,9 @@ pbuf_header(struct pbuf *p, s16_t header_size_increment)
|
||||
u16_t increment_magnitude;
|
||||
|
||||
LWIP_ASSERT("p != NULL", p != NULL);
|
||||
if ((header_size_increment == 0) || (p == NULL))
|
||||
if ((header_size_increment == 0) || (p == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (header_size_increment < 0){
|
||||
increment_magnitude = -header_size_increment;
|
||||
@@ -478,8 +566,7 @@ pbuf_header(struct pbuf *p, s16_t header_size_increment)
|
||||
* bail out unsuccesfully */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* Unknown type */
|
||||
LWIP_ASSERT("bad pbuf type", 0);
|
||||
return 1;
|
||||
@@ -570,15 +657,25 @@ pbuf_free(struct pbuf *p)
|
||||
q = p->next;
|
||||
LWIP_DEBUGF( PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_free: deallocating %p\n", (void *)p));
|
||||
type = p->type;
|
||||
/* is this a pbuf from the pool? */
|
||||
if (type == PBUF_POOL) {
|
||||
memp_free(MEMP_PBUF_POOL, p);
|
||||
/* is this a ROM or RAM referencing pbuf? */
|
||||
} else if (type == PBUF_ROM || type == PBUF_REF) {
|
||||
memp_free(MEMP_PBUF, p);
|
||||
/* type == PBUF_RAM */
|
||||
} else {
|
||||
mem_free(p);
|
||||
#if LWIP_SUPPORT_CUSTOM_PBUF
|
||||
/* is this a custom pbuf? */
|
||||
if ((p->flags & PBUF_FLAG_IS_CUSTOM) != 0) {
|
||||
struct pbuf_custom *pc = (struct pbuf_custom*)p;
|
||||
LWIP_ASSERT("pc->custom_free_function != NULL", pc->custom_free_function != NULL);
|
||||
pc->custom_free_function(p);
|
||||
} else
|
||||
#endif /* LWIP_SUPPORT_CUSTOM_PBUF */
|
||||
{
|
||||
/* is this a pbuf from the pool? */
|
||||
if (type == PBUF_POOL) {
|
||||
memp_free(MEMP_PBUF_POOL, p);
|
||||
/* is this a ROM or RAM referencing pbuf? */
|
||||
} else if (type == PBUF_ROM || type == PBUF_REF) {
|
||||
memp_free(MEMP_PBUF, p);
|
||||
/* type == PBUF_RAM */
|
||||
} else {
|
||||
mem_free(p);
|
||||
}
|
||||
}
|
||||
count++;
|
||||
/* proceed to next pbuf */
|
||||
@@ -766,7 +863,6 @@ pbuf_copy(struct pbuf *p_to, struct pbuf *p_from)
|
||||
/* iterate through pbuf chain */
|
||||
do
|
||||
{
|
||||
LWIP_ASSERT("p_to != NULL", p_to != NULL);
|
||||
/* copy one part of the original chain */
|
||||
if ((p_to->len - offset_to) >= (p_from->len - offset_from)) {
|
||||
/* complete current p_from fits into current p_to */
|
||||
@@ -779,17 +875,18 @@ pbuf_copy(struct pbuf *p_to, struct pbuf *p_from)
|
||||
offset_to += len;
|
||||
offset_from += len;
|
||||
LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len);
|
||||
if (offset_to == p_to->len) {
|
||||
/* on to next p_to (if any) */
|
||||
offset_to = 0;
|
||||
p_to = p_to->next;
|
||||
}
|
||||
LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len);
|
||||
if (offset_from >= p_from->len) {
|
||||
/* on to next p_from (if any) */
|
||||
offset_from = 0;
|
||||
p_from = p_from->next;
|
||||
}
|
||||
if (offset_to == p_to->len) {
|
||||
/* on to next p_to (if any) */
|
||||
offset_to = 0;
|
||||
p_to = p_to->next;
|
||||
LWIP_ERROR("p_to != NULL", (p_to != NULL) || (p_from == NULL) , return ERR_ARG;);
|
||||
}
|
||||
|
||||
if((p_from != NULL) && (p_from->len == p_from->tot_len)) {
|
||||
/* don't copy more than one packet! */
|
||||
@@ -900,8 +997,8 @@ pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len)
|
||||
/**
|
||||
* Creates a single pbuf out of a queue of pbufs.
|
||||
*
|
||||
* @remark: The source pbuf 'p' is not freed by this function because that can
|
||||
* be illegal in some places!
|
||||
* @remark: Either the source pbuf 'p' is freed by this function or the original
|
||||
* pbuf 'p' is returned, therefore the caller has to check the result!
|
||||
*
|
||||
* @param p the source pbuf
|
||||
* @param layer pbuf_layer of the new pbuf
|
||||
@@ -927,3 +1024,156 @@ pbuf_coalesce(struct pbuf *p, pbuf_layer layer)
|
||||
pbuf_free(p);
|
||||
return q;
|
||||
}
|
||||
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
/**
|
||||
* Copies data into a single pbuf (*not* into a pbuf queue!) and updates
|
||||
* the checksum while copying
|
||||
*
|
||||
* @param p the pbuf to copy data into
|
||||
* @param start_offset offset of p->payload where to copy the data to
|
||||
* @param dataptr data to copy into the pbuf
|
||||
* @param len length of data to copy into the pbuf
|
||||
* @param chksum pointer to the checksum which is updated
|
||||
* @return ERR_OK if successful, another error if the data does not fit
|
||||
* within the (first) pbuf (no pbuf queues!)
|
||||
*/
|
||||
err_t
|
||||
pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr,
|
||||
u16_t len, u16_t *chksum)
|
||||
{
|
||||
u32_t acc;
|
||||
u16_t copy_chksum;
|
||||
char *dst_ptr;
|
||||
LWIP_ASSERT("p != NULL", p != NULL);
|
||||
LWIP_ASSERT("dataptr != NULL", dataptr != NULL);
|
||||
LWIP_ASSERT("chksum != NULL", chksum != NULL);
|
||||
LWIP_ASSERT("len != 0", len != 0);
|
||||
|
||||
if ((start_offset >= p->len) || (start_offset + len > p->len)) {
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
dst_ptr = ((char*)p->payload) + start_offset;
|
||||
copy_chksum = LWIP_CHKSUM_COPY(dst_ptr, dataptr, len);
|
||||
if ((start_offset & 1) != 0) {
|
||||
copy_chksum = SWAP_BYTES_IN_WORD(copy_chksum);
|
||||
}
|
||||
acc = *chksum;
|
||||
acc += copy_chksum;
|
||||
*chksum = FOLD_U32T(acc);
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
|
||||
/** Get one byte from the specified position in a pbuf
|
||||
* WARNING: returns zero for offset >= p->tot_len
|
||||
*
|
||||
* @param p pbuf to parse
|
||||
* @param offset offset into p of the byte to return
|
||||
* @return byte at an offset into p OR ZERO IF 'offset' >= p->tot_len
|
||||
*/
|
||||
u8_t
|
||||
pbuf_get_at(struct pbuf* p, u16_t offset)
|
||||
{
|
||||
u16_t copy_from = offset;
|
||||
struct pbuf* q = p;
|
||||
|
||||
/* get the correct pbuf */
|
||||
while ((q != NULL) && (q->len <= copy_from)) {
|
||||
copy_from -= q->len;
|
||||
q = q->next;
|
||||
}
|
||||
/* return requested data if pbuf is OK */
|
||||
if ((q != NULL) && (q->len > copy_from)) {
|
||||
return ((u8_t*)q->payload)[copy_from];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Compare pbuf contents at specified offset with memory s2, both of length n
|
||||
*
|
||||
* @param p pbuf to compare
|
||||
* @param offset offset into p at wich to start comparing
|
||||
* @param s2 buffer to compare
|
||||
* @param n length of buffer to compare
|
||||
* @return zero if equal, nonzero otherwise
|
||||
* (0xffff if p is too short, diffoffset+1 otherwise)
|
||||
*/
|
||||
u16_t
|
||||
pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n)
|
||||
{
|
||||
u16_t start = offset;
|
||||
struct pbuf* q = p;
|
||||
|
||||
/* get the correct pbuf */
|
||||
while ((q != NULL) && (q->len <= start)) {
|
||||
start -= q->len;
|
||||
q = q->next;
|
||||
}
|
||||
/* return requested data if pbuf is OK */
|
||||
if ((q != NULL) && (q->len > start)) {
|
||||
u16_t i;
|
||||
for(i = 0; i < n; i++) {
|
||||
u8_t a = pbuf_get_at(q, start + i);
|
||||
u8_t b = ((u8_t*)s2)[i];
|
||||
if (a != b) {
|
||||
return i+1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
/** Find occurrence of mem (with length mem_len) in pbuf p, starting at offset
|
||||
* start_offset.
|
||||
*
|
||||
* @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as
|
||||
* return value 'not found'
|
||||
* @param mem search for the contents of this buffer
|
||||
* @param mem_len length of 'mem'
|
||||
* @param start_offset offset into p at which to start searching
|
||||
* @return 0xFFFF if substr was not found in p or the index where it was found
|
||||
*/
|
||||
u16_t
|
||||
pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset)
|
||||
{
|
||||
u16_t i;
|
||||
u16_t max = p->tot_len - mem_len;
|
||||
if (p->tot_len >= mem_len + start_offset) {
|
||||
for(i = start_offset; i <= max; ) {
|
||||
u16_t plus = pbuf_memcmp(p, i, mem, mem_len);
|
||||
if (plus == 0) {
|
||||
return i;
|
||||
} else {
|
||||
i += plus;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0xFFFF;
|
||||
}
|
||||
|
||||
/** Find occurrence of substr with length substr_len in pbuf p, start at offset
|
||||
* start_offset
|
||||
* WARNING: in contrast to strstr(), this one does not stop at the first \0 in
|
||||
* the pbuf/source string!
|
||||
*
|
||||
* @param p pbuf to search, maximum length is 0xFFFE since 0xFFFF is used as
|
||||
* return value 'not found'
|
||||
* @param substr string to search for in p, maximum length is 0xFFFE
|
||||
* @return 0xFFFF if substr was not found in p or the index where it was found
|
||||
*/
|
||||
u16_t
|
||||
pbuf_strstr(struct pbuf* p, const char* substr)
|
||||
{
|
||||
size_t substr_len;
|
||||
if ((substr == NULL) || (substr[0] == 0) || (p->tot_len == 0xFFFF)) {
|
||||
return 0xFFFF;
|
||||
}
|
||||
substr_len = strlen(substr);
|
||||
if (substr_len >= 0xFFFF) {
|
||||
return 0xFFFF;
|
||||
}
|
||||
return pbuf_memfind(p, substr, (u16_t)substr_len, 0);
|
||||
}
|
||||
|
||||
@@ -44,12 +44,10 @@
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/raw.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/snmp.h"
|
||||
#include "arch/perf.h"
|
||||
|
||||
#include <string.h>
|
||||
@@ -84,7 +82,7 @@ raw_input(struct pbuf *p, struct netif *inp)
|
||||
|
||||
LWIP_UNUSED_ARG(inp);
|
||||
|
||||
iphdr = p->payload;
|
||||
iphdr = (struct ip_hdr *)p->payload;
|
||||
proto = IPH_PROTO(iphdr);
|
||||
|
||||
prev = NULL;
|
||||
@@ -92,16 +90,18 @@ raw_input(struct pbuf *p, struct netif *inp)
|
||||
/* loop through all raw pcbs until the packet is eaten by one */
|
||||
/* this allows multiple pcbs to match against the packet by design */
|
||||
while ((eaten == 0) && (pcb != NULL)) {
|
||||
if (pcb->protocol == proto) {
|
||||
if ((pcb->protocol == proto) &&
|
||||
(ip_addr_isany(&pcb->local_ip) ||
|
||||
ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest))) {
|
||||
#if IP_SOF_BROADCAST_RECV
|
||||
/* broadcast filter? */
|
||||
if ((pcb->so_options & SOF_BROADCAST) || !ip_addr_isbroadcast(&(iphdr->dest), inp))
|
||||
if (ip_get_option(pcb, SOF_BROADCAST) || !ip_addr_isbroadcast(¤t_iphdr_dest, inp))
|
||||
#endif /* IP_SOF_BROADCAST_RECV */
|
||||
{
|
||||
/* receive callback function available? */
|
||||
if (pcb->recv != NULL) {
|
||||
/* the receive callback function did not eat the packet? */
|
||||
if (pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src)) != 0) {
|
||||
if (pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr()) != 0) {
|
||||
/* receive function ate the packet */
|
||||
p = NULL;
|
||||
eaten = 1;
|
||||
@@ -139,7 +139,7 @@ raw_input(struct pbuf *p, struct netif *inp)
|
||||
* @see raw_disconnect()
|
||||
*/
|
||||
err_t
|
||||
raw_bind(struct raw_pcb *pcb, struct ip_addr *ipaddr)
|
||||
raw_bind(struct raw_pcb *pcb, ip_addr_t *ipaddr)
|
||||
{
|
||||
ip_addr_set(&pcb->local_ip, ipaddr);
|
||||
return ERR_OK;
|
||||
@@ -159,7 +159,7 @@ raw_bind(struct raw_pcb *pcb, struct ip_addr *ipaddr)
|
||||
* @see raw_disconnect() and raw_sendto()
|
||||
*/
|
||||
err_t
|
||||
raw_connect(struct raw_pcb *pcb, struct ip_addr *ipaddr)
|
||||
raw_connect(struct raw_pcb *pcb, ip_addr_t *ipaddr)
|
||||
{
|
||||
ip_addr_set(&pcb->remote_ip, ipaddr);
|
||||
return ERR_OK;
|
||||
@@ -180,10 +180,7 @@ raw_connect(struct raw_pcb *pcb, struct ip_addr *ipaddr)
|
||||
* available for others.
|
||||
*/
|
||||
void
|
||||
raw_recv(struct raw_pcb *pcb,
|
||||
u8_t (* recv)(void *arg, struct raw_pcb *upcb, struct pbuf *p,
|
||||
struct ip_addr *addr),
|
||||
void *recv_arg)
|
||||
raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg)
|
||||
{
|
||||
/* remember recv() callback and user data */
|
||||
pcb->recv = recv;
|
||||
@@ -203,11 +200,11 @@ raw_recv(struct raw_pcb *pcb,
|
||||
*
|
||||
*/
|
||||
err_t
|
||||
raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
|
||||
raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)
|
||||
{
|
||||
err_t err;
|
||||
struct netif *netif;
|
||||
struct ip_addr *src_ip;
|
||||
ip_addr_t *src_ip;
|
||||
struct pbuf *q; /* q will be sent down the stack */
|
||||
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n"));
|
||||
@@ -221,8 +218,10 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n"));
|
||||
return ERR_MEM;
|
||||
}
|
||||
/* chain header q in front of given pbuf p */
|
||||
pbuf_chain(q, p);
|
||||
if (p->tot_len != 0) {
|
||||
/* chain header q in front of given pbuf p */
|
||||
pbuf_chain(q, p);
|
||||
}
|
||||
/* { first pbuf q points to header pbuf } */
|
||||
LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
|
||||
} else {
|
||||
@@ -235,7 +234,8 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
|
||||
}
|
||||
|
||||
if ((netif = ip_route(ipaddr)) == NULL) {
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to 0x%"X32_F"\n", ipaddr->addr));
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
|
||||
/* free any temporary header pbuf allocated by pbuf_header() */
|
||||
if (q != p) {
|
||||
pbuf_free(q);
|
||||
@@ -245,7 +245,7 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
|
||||
|
||||
#if IP_SOF_BROADCAST
|
||||
/* broadcast filter? */
|
||||
if ( ((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(ipaddr, netif) ) {
|
||||
if (!ip_get_option(pcb, SOF_BROADCAST) && ip_addr_isbroadcast(ipaddr, netif)) {
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
|
||||
/* free any temporary header pbuf allocated by pbuf_header() */
|
||||
if (q != p) {
|
||||
@@ -263,13 +263,9 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
|
||||
src_ip = &(pcb->local_ip);
|
||||
}
|
||||
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
netif->addr_hint = &(pcb->addr_hint);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint);
|
||||
err = ip_output_if (q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif);
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
netif->addr_hint = NULL;
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
NETIF_SET_HWADDRHINT(netif, NULL);
|
||||
|
||||
/* did we chain a header earlier? */
|
||||
if (q != p) {
|
||||
@@ -332,12 +328,13 @@ raw_remove(struct raw_pcb *pcb)
|
||||
* @see raw_remove()
|
||||
*/
|
||||
struct raw_pcb *
|
||||
raw_new(u8_t proto) {
|
||||
raw_new(u8_t proto)
|
||||
{
|
||||
struct raw_pcb *pcb;
|
||||
|
||||
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_new\n"));
|
||||
|
||||
pcb = memp_malloc(MEMP_RAW_PCB);
|
||||
pcb = (struct raw_pcb *)memp_malloc(MEMP_RAW_PCB);
|
||||
/* could allocate RAW PCB? */
|
||||
if (pcb != NULL) {
|
||||
/* initialize PCB to all zeroes */
|
||||
|
||||
@@ -61,7 +61,7 @@ snmp_asn1_dec_type(struct pbuf *p, u16_t ofs, u8_t *type)
|
||||
plen += p->len;
|
||||
if (ofs < plen)
|
||||
{
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
msg_ptr += ofs - base;
|
||||
*type = *msg_ptr;
|
||||
return ERR_OK;
|
||||
@@ -94,7 +94,7 @@ snmp_asn1_dec_length(struct pbuf *p, u16_t ofs, u8_t *octets_used, u16_t *length
|
||||
plen += p->len;
|
||||
if (ofs < plen)
|
||||
{
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
msg_ptr += ofs - base;
|
||||
|
||||
if (*msg_ptr < 0x80)
|
||||
@@ -125,7 +125,7 @@ snmp_asn1_dec_length(struct pbuf *p, u16_t ofs, u8_t *octets_used, u16_t *length
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
@@ -160,7 +160,7 @@ snmp_asn1_dec_length(struct pbuf *p, u16_t ofs, u8_t *octets_used, u16_t *length
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -186,7 +186,7 @@ snmp_asn1_dec_length(struct pbuf *p, u16_t ofs, u8_t *octets_used, u16_t *length
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
@@ -249,7 +249,7 @@ snmp_asn1_dec_u32t(struct pbuf *p, u16_t ofs, u16_t len, u32_t *value)
|
||||
plen += p->len;
|
||||
if (ofs < plen)
|
||||
{
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
msg_ptr += ofs - base;
|
||||
if ((len > 0) && (len < 6))
|
||||
{
|
||||
@@ -273,7 +273,7 @@ snmp_asn1_dec_u32t(struct pbuf *p, u16_t ofs, u16_t len, u32_t *value)
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
@@ -295,7 +295,7 @@ snmp_asn1_dec_u32t(struct pbuf *p, u16_t ofs, u16_t len, u32_t *value)
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
@@ -349,7 +349,7 @@ snmp_asn1_dec_s32t(struct pbuf *p, u16_t ofs, u16_t len, s32_t *value)
|
||||
plen += p->len;
|
||||
if (ofs < plen)
|
||||
{
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
msg_ptr += ofs - base;
|
||||
if ((len > 0) && (len < 5))
|
||||
{
|
||||
@@ -386,7 +386,7 @@ snmp_asn1_dec_s32t(struct pbuf *p, u16_t ofs, u16_t len, s32_t *value)
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
@@ -439,7 +439,7 @@ snmp_asn1_dec_oid(struct pbuf *p, u16_t ofs, u16_t len, struct snmp_obj_id *oid)
|
||||
plen += p->len;
|
||||
if (ofs < plen)
|
||||
{
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
msg_ptr += ofs - base;
|
||||
|
||||
oid->len = 0;
|
||||
@@ -493,7 +493,7 @@ snmp_asn1_dec_oid(struct pbuf *p, u16_t ofs, u16_t len, struct snmp_obj_id *oid)
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
@@ -519,7 +519,7 @@ snmp_asn1_dec_oid(struct pbuf *p, u16_t ofs, u16_t len, struct snmp_obj_id *oid)
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
@@ -551,7 +551,7 @@ snmp_asn1_dec_oid(struct pbuf *p, u16_t ofs, u16_t len, struct snmp_obj_id *oid)
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
@@ -607,7 +607,7 @@ snmp_asn1_dec_raw(struct pbuf *p, u16_t ofs, u16_t len, u16_t raw_len, u8_t *raw
|
||||
plen += p->len;
|
||||
if (ofs < plen)
|
||||
{
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
msg_ptr += ofs - base;
|
||||
if (raw_len >= len)
|
||||
{
|
||||
@@ -623,7 +623,7 @@ snmp_asn1_dec_raw(struct pbuf *p, u16_t ofs, u16_t len, u16_t raw_len, u8_t *raw
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -190,7 +190,7 @@ snmp_asn1_enc_type(struct pbuf *p, u16_t ofs, u8_t type)
|
||||
plen += p->len;
|
||||
if (ofs < plen)
|
||||
{
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
msg_ptr += ofs - base;
|
||||
*msg_ptr = type;
|
||||
return ERR_OK;
|
||||
@@ -222,12 +222,12 @@ snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length)
|
||||
plen += p->len;
|
||||
if (ofs < plen)
|
||||
{
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
msg_ptr += ofs - base;
|
||||
|
||||
if (length < 0x80)
|
||||
{
|
||||
*msg_ptr = length;
|
||||
*msg_ptr = (u8_t)length;
|
||||
return ERR_OK;
|
||||
}
|
||||
else if (length < 0x100)
|
||||
@@ -239,14 +239,14 @@ snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length)
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* next octet in same pbuf */
|
||||
msg_ptr++;
|
||||
}
|
||||
*msg_ptr = length;
|
||||
*msg_ptr = (u8_t)length;
|
||||
return ERR_OK;
|
||||
}
|
||||
else
|
||||
@@ -265,7 +265,7 @@ snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length)
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
@@ -276,12 +276,12 @@ snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length)
|
||||
if (i == 0)
|
||||
{
|
||||
/* least significant length octet */
|
||||
*msg_ptr = length;
|
||||
*msg_ptr = (u8_t)length;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* most significant length octet */
|
||||
*msg_ptr = length >> 8;
|
||||
*msg_ptr = (u8_t)(length >> 8);
|
||||
}
|
||||
}
|
||||
return ERR_OK;
|
||||
@@ -305,7 +305,7 @@ snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length)
|
||||
* @see snmp_asn1_enc_u32t_cnt()
|
||||
*/
|
||||
err_t
|
||||
snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, u32_t value)
|
||||
snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, u32_t value)
|
||||
{
|
||||
u16_t plen, base;
|
||||
u8_t *msg_ptr;
|
||||
@@ -317,7 +317,7 @@ snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, u32_t value)
|
||||
plen += p->len;
|
||||
if (ofs < plen)
|
||||
{
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
msg_ptr += ofs - base;
|
||||
|
||||
if (octets_needed == 5)
|
||||
@@ -331,7 +331,7 @@ snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, u32_t value)
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
@@ -343,14 +343,14 @@ snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, u32_t value)
|
||||
while (octets_needed > 1)
|
||||
{
|
||||
octets_needed--;
|
||||
*msg_ptr = value >> (octets_needed << 3);
|
||||
*msg_ptr = (u8_t)(value >> (octets_needed << 3));
|
||||
ofs += 1;
|
||||
if (ofs >= plen)
|
||||
{
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
@@ -360,7 +360,7 @@ snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, u32_t value)
|
||||
}
|
||||
}
|
||||
/* (only) one least significant octet */
|
||||
*msg_ptr = value;
|
||||
*msg_ptr = (u8_t)value;
|
||||
return ERR_OK;
|
||||
}
|
||||
p = p->next;
|
||||
@@ -381,7 +381,7 @@ snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, u32_t value)
|
||||
* @see snmp_asn1_enc_s32t_cnt()
|
||||
*/
|
||||
err_t
|
||||
snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, s32_t value)
|
||||
snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, s32_t value)
|
||||
{
|
||||
u16_t plen, base;
|
||||
u8_t *msg_ptr;
|
||||
@@ -393,20 +393,20 @@ snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, s32_t value)
|
||||
plen += p->len;
|
||||
if (ofs < plen)
|
||||
{
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
msg_ptr += ofs - base;
|
||||
|
||||
while (octets_needed > 1)
|
||||
{
|
||||
octets_needed--;
|
||||
*msg_ptr = value >> (octets_needed << 3);
|
||||
*msg_ptr = (u8_t)(value >> (octets_needed << 3));
|
||||
ofs += 1;
|
||||
if (ofs >= plen)
|
||||
{
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
@@ -416,7 +416,7 @@ snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, s32_t value)
|
||||
}
|
||||
}
|
||||
/* (only) one least significant octet */
|
||||
*msg_ptr = value;
|
||||
*msg_ptr = (u8_t)value;
|
||||
return ERR_OK;
|
||||
}
|
||||
p = p->next;
|
||||
@@ -447,7 +447,7 @@ snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident)
|
||||
plen += p->len;
|
||||
if (ofs < plen)
|
||||
{
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
msg_ptr += ofs - base;
|
||||
|
||||
if (ident_len > 1)
|
||||
@@ -460,7 +460,7 @@ snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident)
|
||||
else
|
||||
{
|
||||
/* calculate prefix */
|
||||
*msg_ptr = (ident[0] * 40) + ident[1];
|
||||
*msg_ptr = (u8_t)((ident[0] * 40) + ident[1]);
|
||||
}
|
||||
ofs += 1;
|
||||
if (ofs >= plen)
|
||||
@@ -468,7 +468,7 @@ snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident)
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
@@ -498,7 +498,7 @@ snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident)
|
||||
{
|
||||
u8_t code;
|
||||
|
||||
code = sub_id >> shift;
|
||||
code = (u8_t)(sub_id >> shift);
|
||||
if ((code != 0) || (tail != 0))
|
||||
{
|
||||
tail = 1;
|
||||
@@ -509,7 +509,7 @@ snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident)
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
@@ -529,7 +529,7 @@ snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident)
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
@@ -559,7 +559,7 @@ snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident)
|
||||
* @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode
|
||||
*/
|
||||
err_t
|
||||
snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u8_t raw_len, u8_t *raw)
|
||||
snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u16_t raw_len, u8_t *raw)
|
||||
{
|
||||
u16_t plen, base;
|
||||
u8_t *msg_ptr;
|
||||
@@ -571,7 +571,7 @@ snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u8_t raw_len, u8_t *raw)
|
||||
plen += p->len;
|
||||
if (ofs < plen)
|
||||
{
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
msg_ptr += ofs - base;
|
||||
|
||||
while (raw_len > 1)
|
||||
@@ -586,7 +586,7 @@ snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u8_t raw_len, u8_t *raw)
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr = (u8_t*)p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -37,7 +37,8 @@
|
||||
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/snmp_structs.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
/** .iso.org.dod.internet address prefix, @see snmp_iso_*() */
|
||||
const s32_t prefix[4] = {1, 3, 6, 1};
|
||||
@@ -94,7 +95,7 @@ void
|
||||
snmp_ifindextonetif(s32_t ifindex, struct netif **netif)
|
||||
{
|
||||
struct netif *nif = netif_list;
|
||||
u16_t i, ifidx;
|
||||
s32_t i, ifidx;
|
||||
|
||||
ifidx = ifindex - 1;
|
||||
i = 0;
|
||||
@@ -132,18 +133,9 @@ snmp_netiftoifindex(struct netif *netif, s32_t *ifidx)
|
||||
* @param ip points to output struct
|
||||
*/
|
||||
void
|
||||
snmp_oidtoip(s32_t *ident, struct ip_addr *ip)
|
||||
snmp_oidtoip(s32_t *ident, ip_addr_t *ip)
|
||||
{
|
||||
u32_t ipa;
|
||||
|
||||
ipa = ident[0];
|
||||
ipa <<= 8;
|
||||
ipa |= ident[1];
|
||||
ipa <<= 8;
|
||||
ipa |= ident[2];
|
||||
ipa <<= 8;
|
||||
ipa |= ident[3];
|
||||
ip->addr = ipa;
|
||||
IP4_ADDR(ip, ident[0], ident[1], ident[2], ident[3]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,15 +144,12 @@ snmp_oidtoip(s32_t *ident, struct ip_addr *ip)
|
||||
* @param ident points to s32_t ident[4] output
|
||||
*/
|
||||
void
|
||||
snmp_iptooid(struct ip_addr *ip, s32_t *ident)
|
||||
snmp_iptooid(ip_addr_t *ip, s32_t *ident)
|
||||
{
|
||||
u32_t ipa;
|
||||
|
||||
ipa = ip->addr;
|
||||
ident[0] = (ipa >> 24) & 0xff;
|
||||
ident[1] = (ipa >> 16) & 0xff;
|
||||
ident[2] = (ipa >> 8) & 0xff;
|
||||
ident[3] = ipa & 0xff;
|
||||
ident[0] = ip4_addr1(ip);
|
||||
ident[1] = ip4_addr2(ip);
|
||||
ident[2] = ip4_addr3(ip);
|
||||
ident[3] = ip4_addr4(ip);
|
||||
}
|
||||
|
||||
struct mib_list_node *
|
||||
@@ -168,7 +157,7 @@ snmp_mib_ln_alloc(s32_t id)
|
||||
{
|
||||
struct mib_list_node *ln;
|
||||
|
||||
ln = (struct mib_list_node *)mem_malloc(sizeof(struct mib_list_node));
|
||||
ln = (struct mib_list_node *)memp_malloc(MEMP_SNMP_NODE);
|
||||
if (ln != NULL)
|
||||
{
|
||||
ln->prev = NULL;
|
||||
@@ -182,7 +171,7 @@ snmp_mib_ln_alloc(s32_t id)
|
||||
void
|
||||
snmp_mib_ln_free(struct mib_list_node *ln)
|
||||
{
|
||||
mem_free(ln);
|
||||
memp_free(MEMP_SNMP_NODE, ln);
|
||||
}
|
||||
|
||||
struct mib_list_rootnode *
|
||||
@@ -190,7 +179,7 @@ snmp_mib_lrn_alloc(void)
|
||||
{
|
||||
struct mib_list_rootnode *lrn;
|
||||
|
||||
lrn = (struct mib_list_rootnode*)mem_malloc(sizeof(struct mib_list_rootnode));
|
||||
lrn = (struct mib_list_rootnode*)memp_malloc(MEMP_SNMP_ROOTNODE);
|
||||
if (lrn != NULL)
|
||||
{
|
||||
lrn->get_object_def = noleafs_get_object_def;
|
||||
@@ -209,7 +198,7 @@ snmp_mib_lrn_alloc(void)
|
||||
void
|
||||
snmp_mib_lrn_free(struct mib_list_rootnode *lrn)
|
||||
{
|
||||
mem_free(lrn);
|
||||
memp_free(MEMP_SNMP_ROOTNODE, lrn);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -456,7 +445,7 @@ snmp_mib_node_delete(struct mib_list_rootnode *rn, struct mib_list_node *n)
|
||||
* @param node points to the root of the tree ('.internet')
|
||||
* @param ident_len the length of the supplied object identifier
|
||||
* @param ident points to the array of sub identifiers
|
||||
* @param np points to the found object instance (rerurn)
|
||||
* @param np points to the found object instance (return)
|
||||
* @return pointer to the requested parent (!) node if success, NULL otherwise
|
||||
*/
|
||||
struct mib_node *
|
||||
@@ -753,7 +742,8 @@ snmp_expand_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snm
|
||||
|
||||
LWIP_DEBUGF(SNMP_MIB_DEBUG,("non-leaf node\n"));
|
||||
/* non-leaf, store right child ptr and id */
|
||||
j = i + 1;
|
||||
LWIP_ASSERT("i < 0xff", i < 0xff);
|
||||
j = (u8_t)i + 1;
|
||||
while ((j < an->maxlength) && (empty_table(an->nptr[j])))
|
||||
{
|
||||
j++;
|
||||
@@ -995,7 +985,8 @@ snmp_expand_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snm
|
||||
|
||||
LWIP_DEBUGF(SNMP_MIB_DEBUG,("non-leaf node\n"));
|
||||
/* non-leaf, store right child ptr and id */
|
||||
j = i + 1;
|
||||
LWIP_ASSERT("i < 0xff", i < 0xff);
|
||||
j = (u8_t)i + 1;
|
||||
if (j < len)
|
||||
{
|
||||
/* right node is the current external node */
|
||||
|
||||
@@ -36,14 +36,14 @@
|
||||
|
||||
#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/snmp.h"
|
||||
#include "lwip/snmp_asn1.h"
|
||||
#include "lwip/snmp_msg.h"
|
||||
#include "lwip/snmp_structs.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -58,7 +58,7 @@ struct snmp_msg_pstat msg_input_list[SNMP_CONCURRENT_REQUESTS];
|
||||
/* UDP Protocol Control Block */
|
||||
struct udp_pcb *snmp1_pcb;
|
||||
|
||||
static void snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);
|
||||
static void snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port);
|
||||
static err_t snmp_pdu_header_check(struct pbuf *p, u16_t ofs, u16_t pdu_len, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat);
|
||||
static err_t snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat);
|
||||
|
||||
@@ -88,6 +88,15 @@ snmp_init(void)
|
||||
msg_ps++;
|
||||
}
|
||||
trap_msg.pcb = snmp1_pcb;
|
||||
|
||||
#ifdef SNMP_PRIVATE_MIB_INIT
|
||||
/* If defined, this must be a function-like define to initialize the
|
||||
* private MIB after the stack has been initialized.
|
||||
* The private MIB can also be initialized in tcpip_callback (or after
|
||||
* the stack is initialized), this define is only for convenience. */
|
||||
SNMP_PRIVATE_MIB_INIT();
|
||||
#endif /* SNMP_PRIVATE_MIB_INIT */
|
||||
|
||||
/* The coldstart trap will only be output
|
||||
if our outgoing interface is up & configured */
|
||||
snmp_coldstart_trap();
|
||||
@@ -96,13 +105,28 @@ snmp_init(void)
|
||||
static void
|
||||
snmp_error_response(struct snmp_msg_pstat *msg_ps, u8_t error)
|
||||
{
|
||||
/* move names back from outvb to invb */
|
||||
int v;
|
||||
struct snmp_varbind *vbi = msg_ps->invb.head;
|
||||
struct snmp_varbind *vbo = msg_ps->outvb.head;
|
||||
for (v=0; v<msg_ps->vb_idx; v++) {
|
||||
vbi->ident_len = vbo->ident_len;
|
||||
vbo->ident_len = 0;
|
||||
vbi->ident = vbo->ident;
|
||||
vbo->ident = NULL;
|
||||
vbi = vbi->next;
|
||||
vbo = vbo->next;
|
||||
}
|
||||
/* free outvb */
|
||||
snmp_varbind_list_free(&msg_ps->outvb);
|
||||
/* we send invb back */
|
||||
msg_ps->outvb = msg_ps->invb;
|
||||
msg_ps->invb.head = NULL;
|
||||
msg_ps->invb.tail = NULL;
|
||||
msg_ps->invb.count = 0;
|
||||
msg_ps->error_status = error;
|
||||
msg_ps->error_index = 1 + msg_ps->vb_idx;
|
||||
/* error index must be 0 for error too big */
|
||||
msg_ps->error_index = (error != SNMP_ES_TOOBIG) ? (1 + msg_ps->vb_idx) : 0;
|
||||
snmp_send_response(msg_ps);
|
||||
snmp_varbind_list_free(&msg_ps->outvb);
|
||||
msg_ps->state = SNMP_MSG_EMPTY;
|
||||
@@ -150,7 +174,8 @@ snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
|
||||
|
||||
/* translate answer into a known lifeform */
|
||||
en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def);
|
||||
if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE)
|
||||
if ((msg_ps->ext_object_def.instance != MIB_OBJECT_NONE) &&
|
||||
(msg_ps->ext_object_def.access & MIB_ACCESS_READ))
|
||||
{
|
||||
msg_ps->state = SNMP_MSG_EXTERNAL_GET_VALUE;
|
||||
en->get_value_q(request_id, &msg_ps->ext_object_def);
|
||||
@@ -171,8 +196,7 @@ snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
|
||||
en = msg_ps->ext_mib_node;
|
||||
|
||||
/* allocate output varbind */
|
||||
vb = (struct snmp_varbind *)mem_malloc(sizeof(struct snmp_varbind));
|
||||
LWIP_ASSERT("vb != NULL",vb != NULL);
|
||||
vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND);
|
||||
if (vb != NULL)
|
||||
{
|
||||
vb->next = NULL;
|
||||
@@ -186,11 +210,12 @@ snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
|
||||
msg_ps->vb_ptr->ident_len = 0;
|
||||
|
||||
vb->value_type = msg_ps->ext_object_def.asn_type;
|
||||
vb->value_len = msg_ps->ext_object_def.v_len;
|
||||
LWIP_ASSERT("invalid length", msg_ps->ext_object_def.v_len <= 0xff);
|
||||
vb->value_len = (u8_t)msg_ps->ext_object_def.v_len;
|
||||
if (vb->value_len > 0)
|
||||
{
|
||||
vb->value = mem_malloc(vb->value_len);
|
||||
LWIP_ASSERT("vb->value != NULL",vb->value != NULL);
|
||||
LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low", vb->value_len <= SNMP_MAX_VALUE_SIZE);
|
||||
vb->value = memp_malloc(MEMP_SNMP_VALUE);
|
||||
if (vb->value != NULL)
|
||||
{
|
||||
en->get_value_a(request_id, &msg_ps->ext_object_def, vb->value_len, vb->value);
|
||||
@@ -205,7 +230,7 @@ snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
|
||||
LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: no variable space\n"));
|
||||
msg_ps->vb_ptr->ident = vb->ident;
|
||||
msg_ps->vb_ptr->ident_len = vb->ident_len;
|
||||
mem_free(vb);
|
||||
memp_free(MEMP_SNMP_VARBIND, vb);
|
||||
snmp_error_response(msg_ps,SNMP_ES_TOOBIG);
|
||||
}
|
||||
}
|
||||
@@ -268,7 +293,8 @@ snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
|
||||
|
||||
msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF;
|
||||
mn->get_object_def(np.ident_len, np.ident, &object_def);
|
||||
if (object_def.instance != MIB_OBJECT_NONE)
|
||||
if ((object_def.instance != MIB_OBJECT_NONE) &&
|
||||
(object_def.access & MIB_ACCESS_READ))
|
||||
{
|
||||
mn = mn;
|
||||
}
|
||||
@@ -283,8 +309,7 @@ snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
|
||||
|
||||
msg_ps->state = SNMP_MSG_INTERNAL_GET_VALUE;
|
||||
/* allocate output varbind */
|
||||
vb = (struct snmp_varbind *)mem_malloc(sizeof(struct snmp_varbind));
|
||||
LWIP_ASSERT("vb != NULL",vb != NULL);
|
||||
vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND);
|
||||
if (vb != NULL)
|
||||
{
|
||||
vb->next = NULL;
|
||||
@@ -298,11 +323,13 @@ snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
|
||||
msg_ps->vb_ptr->ident_len = 0;
|
||||
|
||||
vb->value_type = object_def.asn_type;
|
||||
vb->value_len = object_def.v_len;
|
||||
LWIP_ASSERT("invalid length", object_def.v_len <= 0xff);
|
||||
vb->value_len = (u8_t)object_def.v_len;
|
||||
if (vb->value_len > 0)
|
||||
{
|
||||
vb->value = mem_malloc(vb->value_len);
|
||||
LWIP_ASSERT("vb->value != NULL",vb->value != NULL);
|
||||
LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low",
|
||||
vb->value_len <= SNMP_MAX_VALUE_SIZE);
|
||||
vb->value = memp_malloc(MEMP_SNMP_VALUE);
|
||||
if (vb->value != NULL)
|
||||
{
|
||||
mn->get_value(&object_def, vb->value_len, vb->value);
|
||||
@@ -315,7 +342,9 @@ snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
|
||||
LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: couldn't allocate variable space\n"));
|
||||
msg_ps->vb_ptr->ident = vb->ident;
|
||||
msg_ps->vb_ptr->ident_len = vb->ident_len;
|
||||
mem_free(vb);
|
||||
vb->ident = NULL;
|
||||
vb->ident_len = 0;
|
||||
memp_free(MEMP_SNMP_VARBIND, vb);
|
||||
snmp_error_response(msg_ps,SNMP_ES_TOOBIG);
|
||||
}
|
||||
}
|
||||
@@ -394,9 +423,10 @@ snmp_msg_getnext_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
|
||||
/* get_value() answer */
|
||||
en = msg_ps->ext_mib_node;
|
||||
|
||||
LWIP_ASSERT("invalid length", msg_ps->ext_object_def.v_len <= 0xff);
|
||||
vb = snmp_varbind_alloc(&msg_ps->ext_oid,
|
||||
msg_ps->ext_object_def.asn_type,
|
||||
msg_ps->ext_object_def.v_len);
|
||||
(u8_t)msg_ps->ext_object_def.v_len);
|
||||
if (vb != NULL)
|
||||
{
|
||||
en->get_value_a(request_id, &msg_ps->ext_object_def, vb->value_len, vb->value);
|
||||
@@ -468,7 +498,8 @@ snmp_msg_getnext_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
|
||||
msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF;
|
||||
mn->get_object_def(1, &oid.id[oid.len - 1], &object_def);
|
||||
|
||||
vb = snmp_varbind_alloc(&oid, object_def.asn_type, object_def.v_len);
|
||||
LWIP_ASSERT("invalid length", object_def.v_len <= 0xff);
|
||||
vb = snmp_varbind_alloc(&oid, object_def.asn_type, (u8_t)object_def.v_len);
|
||||
if (vb != NULL)
|
||||
{
|
||||
msg_ps->state = SNMP_MSG_INTERNAL_GET_VALUE;
|
||||
@@ -538,7 +569,7 @@ snmp_msg_set_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
|
||||
/* set_test() answer*/
|
||||
en = msg_ps->ext_mib_node;
|
||||
|
||||
if (msg_ps->ext_object_def.access == MIB_OBJECT_READ_WRITE)
|
||||
if (msg_ps->ext_object_def.access & MIB_ACCESS_WRITE)
|
||||
{
|
||||
if ((msg_ps->ext_object_def.asn_type == msg_ps->vb_ptr->value_type) &&
|
||||
(en->set_test_a(request_id,&msg_ps->ext_object_def,
|
||||
@@ -653,7 +684,7 @@ snmp_msg_set_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
|
||||
{
|
||||
msg_ps->state = SNMP_MSG_INTERNAL_SET_TEST;
|
||||
|
||||
if (object_def.access == MIB_OBJECT_READ_WRITE)
|
||||
if (object_def.access & MIB_ACCESS_WRITE)
|
||||
{
|
||||
if ((object_def.asn_type == msg_ps->vb_ptr->value_type) &&
|
||||
(mn->set_test(&object_def,msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value) != 0))
|
||||
@@ -788,123 +819,85 @@ snmp_msg_event(u8_t request_id)
|
||||
|
||||
/* lwIP UDP receive callback function */
|
||||
static void
|
||||
snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
|
||||
snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
|
||||
{
|
||||
struct udp_hdr *udphdr;
|
||||
struct snmp_msg_pstat *msg_ps;
|
||||
u8_t req_idx;
|
||||
err_t err_ret;
|
||||
u16_t payload_len = p->tot_len;
|
||||
u16_t payload_ofs = 0;
|
||||
u16_t varbind_ofs = 0;
|
||||
|
||||
/* suppress unused argument warning */
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
/* peek in the UDP header (goto IP payload) */
|
||||
if(pbuf_header(p, UDP_HLEN)){
|
||||
LWIP_ASSERT("Can't move to UDP header", 0);
|
||||
|
||||
/* traverse input message process list, look for SNMP_MSG_EMPTY */
|
||||
msg_ps = &msg_input_list[0];
|
||||
req_idx = 0;
|
||||
while ((req_idx < SNMP_CONCURRENT_REQUESTS) && (msg_ps->state != SNMP_MSG_EMPTY))
|
||||
{
|
||||
req_idx++;
|
||||
msg_ps++;
|
||||
}
|
||||
if (req_idx == SNMP_CONCURRENT_REQUESTS)
|
||||
{
|
||||
/* exceeding number of concurrent requests */
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
udphdr = p->payload;
|
||||
|
||||
/* check if datagram is really directed at us (including broadcast requests) */
|
||||
if ((pcb == snmp1_pcb) && (ntohs(udphdr->dest) == SNMP_IN_PORT))
|
||||
/* accepting request */
|
||||
snmp_inc_snmpinpkts();
|
||||
/* record used 'protocol control block' */
|
||||
msg_ps->pcb = pcb;
|
||||
/* source address (network order) */
|
||||
msg_ps->sip = *addr;
|
||||
/* source port (host order (lwIP oddity)) */
|
||||
msg_ps->sp = port;
|
||||
|
||||
/* check total length, version, community, pdu type */
|
||||
err_ret = snmp_pdu_header_check(p, payload_ofs, payload_len, &varbind_ofs, msg_ps);
|
||||
/* Only accept requests and requests without error (be robust) */
|
||||
/* Reject response and trap headers or error requests as input! */
|
||||
if ((err_ret != ERR_OK) ||
|
||||
((msg_ps->rt != SNMP_ASN1_PDU_GET_REQ) &&
|
||||
(msg_ps->rt != SNMP_ASN1_PDU_GET_NEXT_REQ) &&
|
||||
(msg_ps->rt != SNMP_ASN1_PDU_SET_REQ)) ||
|
||||
((msg_ps->error_status != SNMP_ES_NOERROR) ||
|
||||
(msg_ps->error_index != 0)) )
|
||||
{
|
||||
struct snmp_msg_pstat *msg_ps;
|
||||
u8_t req_idx;
|
||||
|
||||
/* traverse input message process list, look for SNMP_MSG_EMPTY */
|
||||
msg_ps = &msg_input_list[0];
|
||||
req_idx = 0;
|
||||
while ((req_idx<SNMP_CONCURRENT_REQUESTS) && (msg_ps->state != SNMP_MSG_EMPTY))
|
||||
{
|
||||
req_idx++;
|
||||
msg_ps++;
|
||||
}
|
||||
if (req_idx != SNMP_CONCURRENT_REQUESTS)
|
||||
{
|
||||
err_t err_ret;
|
||||
u16_t payload_len;
|
||||
u16_t payload_ofs;
|
||||
u16_t varbind_ofs = 0;
|
||||
|
||||
/* accepting request */
|
||||
snmp_inc_snmpinpkts();
|
||||
/* record used 'protocol control block' */
|
||||
msg_ps->pcb = pcb;
|
||||
/* source address (network order) */
|
||||
msg_ps->sip = *addr;
|
||||
/* source port (host order (lwIP oddity)) */
|
||||
msg_ps->sp = port;
|
||||
/* read UDP payload length from UDP header */
|
||||
payload_len = ntohs(udphdr->len) - UDP_HLEN;
|
||||
|
||||
/* adjust to UDP payload */
|
||||
payload_ofs = UDP_HLEN;
|
||||
|
||||
/* check total length, version, community, pdu type */
|
||||
err_ret = snmp_pdu_header_check(p, payload_ofs, payload_len, &varbind_ofs, msg_ps);
|
||||
if (((msg_ps->rt == SNMP_ASN1_PDU_GET_REQ) ||
|
||||
(msg_ps->rt == SNMP_ASN1_PDU_GET_NEXT_REQ) ||
|
||||
(msg_ps->rt == SNMP_ASN1_PDU_SET_REQ)) &&
|
||||
((msg_ps->error_status == SNMP_ES_NOERROR) &&
|
||||
(msg_ps->error_index == 0)) )
|
||||
{
|
||||
/* Only accept requests and requests without error (be robust) */
|
||||
err_ret = err_ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reject response and trap headers or error requests as input! */
|
||||
err_ret = ERR_ARG;
|
||||
}
|
||||
if (err_ret == ERR_OK)
|
||||
{
|
||||
LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv ok, community %s\n", msg_ps->community));
|
||||
|
||||
/* Builds a list of variable bindings. Copy the varbinds from the pbuf
|
||||
chain to glue them when these are divided over two or more pbuf's. */
|
||||
err_ret = snmp_pdu_dec_varbindlist(p, varbind_ofs, &varbind_ofs, msg_ps);
|
||||
if ((err_ret == ERR_OK) && (msg_ps->invb.count > 0))
|
||||
{
|
||||
/* we've decoded the incoming message, release input msg now */
|
||||
pbuf_free(p);
|
||||
|
||||
msg_ps->error_status = SNMP_ES_NOERROR;
|
||||
msg_ps->error_index = 0;
|
||||
/* find object for each variable binding */
|
||||
msg_ps->state = SNMP_MSG_SEARCH_OBJ;
|
||||
/* first variable binding from list to inspect */
|
||||
msg_ps->vb_idx = 0;
|
||||
|
||||
LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv varbind cnt=%"U16_F"\n",(u16_t)msg_ps->invb.count));
|
||||
|
||||
/* handle input event and as much objects as possible in one go */
|
||||
snmp_msg_event(req_idx);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* varbind-list decode failed, or varbind list empty.
|
||||
drop request silently, do not return error!
|
||||
(errors are only returned for a specific varbind failure) */
|
||||
pbuf_free(p);
|
||||
LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_dec_varbindlist() failed\n"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* header check failed
|
||||
drop request silently, do not return error! */
|
||||
pbuf_free(p);
|
||||
LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_header_check() failed\n"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* exceeding number of concurrent requests */
|
||||
pbuf_free(p);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* datagram not for us */
|
||||
/* header check failed drop request silently, do not return error! */
|
||||
pbuf_free(p);
|
||||
LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_header_check() failed\n"));
|
||||
return;
|
||||
}
|
||||
LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv ok, community %s\n", msg_ps->community));
|
||||
|
||||
/* Builds a list of variable bindings. Copy the varbinds from the pbuf
|
||||
chain to glue them when these are divided over two or more pbuf's. */
|
||||
err_ret = snmp_pdu_dec_varbindlist(p, varbind_ofs, &varbind_ofs, msg_ps);
|
||||
/* we've decoded the incoming message, release input msg now */
|
||||
pbuf_free(p);
|
||||
if ((err_ret != ERR_OK) || (msg_ps->invb.count == 0))
|
||||
{
|
||||
/* varbind-list decode failed, or varbind list empty.
|
||||
drop request silently, do not return error!
|
||||
(errors are only returned for a specific varbind failure) */
|
||||
LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_dec_varbindlist() failed\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
msg_ps->error_status = SNMP_ES_NOERROR;
|
||||
msg_ps->error_index = 0;
|
||||
/* find object for each variable binding */
|
||||
msg_ps->state = SNMP_MSG_SEARCH_OBJ;
|
||||
/* first variable binding from list to inspect */
|
||||
msg_ps->vb_idx = 0;
|
||||
|
||||
LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv varbind cnt=%"U16_F"\n",(u16_t)msg_ps->invb.count));
|
||||
|
||||
/* handle input event and as much objects as possible in one go */
|
||||
snmp_msg_event(req_idx);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -978,7 +971,7 @@ snmp_pdu_header_check(struct pbuf *p, u16_t ofs, u16_t pdu_len, u16_t *ofs_ret,
|
||||
/* add zero terminator */
|
||||
len = ((len < (SNMP_COMMUNITY_STR_LEN))?(len):(SNMP_COMMUNITY_STR_LEN));
|
||||
m_stat->community[len] = 0;
|
||||
m_stat->com_strlen = len;
|
||||
m_stat->com_strlen = (u8_t)len;
|
||||
if (strncmp(snmp_publiccommunity, (const char*)m_stat->community, SNMP_COMMUNITY_STR_LEN) != 0)
|
||||
{
|
||||
/** @todo: move this if we need to check more names */
|
||||
@@ -1195,7 +1188,7 @@ snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_
|
||||
vb = snmp_varbind_alloc(&oid, type, sizeof(s32_t));
|
||||
if (vb != NULL)
|
||||
{
|
||||
s32_t *vptr = vb->value;
|
||||
s32_t *vptr = (s32_t*)vb->value;
|
||||
|
||||
derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, vptr);
|
||||
snmp_varbind_tail_add(&m_stat->invb, vb);
|
||||
@@ -1211,7 +1204,7 @@ snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_
|
||||
vb = snmp_varbind_alloc(&oid, type, sizeof(u32_t));
|
||||
if (vb != NULL)
|
||||
{
|
||||
u32_t *vptr = vb->value;
|
||||
u32_t *vptr = (u32_t*)vb->value;
|
||||
|
||||
derr = snmp_asn1_dec_u32t(p, ofs + 1 + len_octets, len, vptr);
|
||||
snmp_varbind_tail_add(&m_stat->invb, vb);
|
||||
@@ -1223,10 +1216,11 @@ snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_
|
||||
break;
|
||||
case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR):
|
||||
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE):
|
||||
vb = snmp_varbind_alloc(&oid, type, len);
|
||||
LWIP_ASSERT("invalid length", len <= 0xff);
|
||||
vb = snmp_varbind_alloc(&oid, type, (u8_t)len);
|
||||
if (vb != NULL)
|
||||
{
|
||||
derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, vb->value_len, vb->value);
|
||||
derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, vb->value_len, (u8_t*)vb->value);
|
||||
snmp_varbind_tail_add(&m_stat->invb, vb);
|
||||
}
|
||||
else
|
||||
@@ -1254,7 +1248,7 @@ snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_
|
||||
if (vb != NULL)
|
||||
{
|
||||
u8_t i = oid_value.len;
|
||||
s32_t *vptr = vb->value;
|
||||
s32_t *vptr = (s32_t*)vb->value;
|
||||
|
||||
while(i > 0)
|
||||
{
|
||||
@@ -1277,7 +1271,7 @@ snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_
|
||||
vb = snmp_varbind_alloc(&oid, type, 4);
|
||||
if (vb != NULL)
|
||||
{
|
||||
derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, vb->value_len, vb->value);
|
||||
derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, vb->value_len, (u8_t*)vb->value);
|
||||
snmp_varbind_tail_add(&m_stat->invb, vb);
|
||||
}
|
||||
else
|
||||
@@ -1323,8 +1317,7 @@ snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len)
|
||||
{
|
||||
struct snmp_varbind *vb;
|
||||
|
||||
vb = (struct snmp_varbind *)mem_malloc(sizeof(struct snmp_varbind));
|
||||
LWIP_ASSERT("vb != NULL",vb != NULL);
|
||||
vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND);
|
||||
if (vb != NULL)
|
||||
{
|
||||
u8_t i;
|
||||
@@ -1335,12 +1328,13 @@ snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len)
|
||||
vb->ident_len = i;
|
||||
if (i > 0)
|
||||
{
|
||||
LWIP_ASSERT("SNMP_MAX_TREE_DEPTH is configured too low", i <= SNMP_MAX_TREE_DEPTH);
|
||||
/* allocate array of s32_t for our object identifier */
|
||||
vb->ident = (s32_t*)mem_malloc(sizeof(s32_t) * i);
|
||||
LWIP_ASSERT("vb->ident != NULL",vb->ident != NULL);
|
||||
vb->ident = (s32_t*)memp_malloc(MEMP_SNMP_VALUE);
|
||||
if (vb->ident == NULL)
|
||||
{
|
||||
mem_free(vb);
|
||||
LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_varbind_alloc: couldn't allocate ident value space\n"));
|
||||
memp_free(MEMP_SNMP_VARBIND, vb);
|
||||
return NULL;
|
||||
}
|
||||
while(i > 0)
|
||||
@@ -1358,16 +1352,17 @@ snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len)
|
||||
vb->value_len = len;
|
||||
if (len > 0)
|
||||
{
|
||||
LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low", vb->value_len <= SNMP_MAX_VALUE_SIZE);
|
||||
/* allocate raw bytes for our object value */
|
||||
vb->value = mem_malloc(len);
|
||||
LWIP_ASSERT("vb->value != NULL",vb->value != NULL);
|
||||
vb->value = memp_malloc(MEMP_SNMP_VALUE);
|
||||
if (vb->value == NULL)
|
||||
{
|
||||
LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_varbind_alloc: couldn't allocate value space\n"));
|
||||
if (vb->ident != NULL)
|
||||
{
|
||||
mem_free(vb->ident);
|
||||
memp_free(MEMP_SNMP_VALUE, vb->ident);
|
||||
}
|
||||
mem_free(vb);
|
||||
memp_free(MEMP_SNMP_VARBIND, vb);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -1377,6 +1372,10 @@ snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len)
|
||||
vb->value = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_varbind_alloc: couldn't allocate varbind space\n"));
|
||||
}
|
||||
return vb;
|
||||
}
|
||||
|
||||
@@ -1385,13 +1384,13 @@ snmp_varbind_free(struct snmp_varbind *vb)
|
||||
{
|
||||
if (vb->value != NULL )
|
||||
{
|
||||
mem_free(vb->value);
|
||||
memp_free(MEMP_SNMP_VALUE, vb->value);
|
||||
}
|
||||
if (vb->ident != NULL )
|
||||
{
|
||||
mem_free(vb->ident);
|
||||
memp_free(MEMP_SNMP_VALUE, vb->ident);
|
||||
}
|
||||
mem_free(vb);
|
||||
memp_free(MEMP_SNMP_VARBIND, vb);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
struct snmp_trap_dst
|
||||
{
|
||||
/* destination IP address in network order */
|
||||
struct ip_addr dip;
|
||||
ip_addr_t dip;
|
||||
/* set to 0 when disabled, >0 when enabled */
|
||||
u8_t enable;
|
||||
};
|
||||
@@ -92,11 +92,11 @@ snmp_trap_dst_enable(u8_t dst_idx, u8_t enable)
|
||||
* @param dst IPv4 address in host order.
|
||||
*/
|
||||
void
|
||||
snmp_trap_dst_ip_set(u8_t dst_idx, struct ip_addr *dst)
|
||||
snmp_trap_dst_ip_set(u8_t dst_idx, ip_addr_t *dst)
|
||||
{
|
||||
if (dst_idx < SNMP_TRAP_DESTINATIONS)
|
||||
{
|
||||
trap_dst[dst_idx].dip.addr = htonl(dst->addr);
|
||||
ip_addr_set(&trap_dst[dst_idx].dip, dst);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,14 +145,7 @@ snmp_send_response(struct snmp_msg_pstat *m_stat)
|
||||
|
||||
/* pass 1, size error, encode packet ino the pbuf(s) */
|
||||
ofs = snmp_resp_header_enc(m_stat, p);
|
||||
if (m_stat->error_status == SNMP_ES_TOOBIG)
|
||||
{
|
||||
snmp_varbind_list_enc(&emptyvb, p, ofs);
|
||||
}
|
||||
else
|
||||
{
|
||||
snmp_varbind_list_enc(&m_stat->outvb, p, ofs);
|
||||
}
|
||||
snmp_varbind_list_enc(&m_stat->outvb, p, ofs);
|
||||
|
||||
switch (m_stat->error_status)
|
||||
{
|
||||
@@ -221,23 +214,24 @@ snmp_send_trap(s8_t generic_trap, struct snmp_obj_id *eoid, s32_t specific_trap)
|
||||
{
|
||||
struct snmp_trap_dst *td;
|
||||
struct netif *dst_if;
|
||||
struct ip_addr dst_ip;
|
||||
ip_addr_t dst_ip;
|
||||
struct pbuf *p;
|
||||
u16_t i,tot_len;
|
||||
|
||||
for (i=0, td = &trap_dst[0]; i<SNMP_TRAP_DESTINATIONS; i++, td++)
|
||||
{
|
||||
if ((td->enable != 0) && (td->dip.addr != 0))
|
||||
if ((td->enable != 0) && !ip_addr_isany(&td->dip))
|
||||
{
|
||||
/* network order trap destination */
|
||||
trap_msg.dip.addr = td->dip.addr;
|
||||
ip_addr_copy(trap_msg.dip, td->dip);
|
||||
/* lookup current source address for this dst */
|
||||
dst_if = ip_route(&td->dip);
|
||||
dst_ip.addr = ntohl(dst_if->ip_addr.addr);
|
||||
trap_msg.sip_raw[0] = dst_ip.addr >> 24;
|
||||
trap_msg.sip_raw[1] = dst_ip.addr >> 16;
|
||||
trap_msg.sip_raw[2] = dst_ip.addr >> 8;
|
||||
trap_msg.sip_raw[3] = dst_ip.addr;
|
||||
ip_addr_copy(dst_ip, dst_if->ip_addr);
|
||||
/* @todo: what about IPv6? */
|
||||
trap_msg.sip_raw[0] = ip4_addr1(&dst_ip);
|
||||
trap_msg.sip_raw[1] = ip4_addr2(&dst_ip);
|
||||
trap_msg.sip_raw[2] = ip4_addr3(&dst_ip);
|
||||
trap_msg.sip_raw[3] = ip4_addr4(&dst_ip);
|
||||
trap_msg.gen_trap = generic_trap;
|
||||
trap_msg.spc_trap = specific_trap;
|
||||
if (generic_trap == SNMP_GENTRAP_ENTERPRISESPC)
|
||||
@@ -269,11 +263,8 @@ snmp_send_trap(s8_t generic_trap, struct snmp_obj_id *eoid, s32_t specific_trap)
|
||||
snmp_inc_snmpouttraps();
|
||||
snmp_inc_snmpoutpkts();
|
||||
|
||||
/** connect to the TRAP destination */
|
||||
udp_connect(trap_msg.pcb, &trap_msg.dip, SNMP_TRAP_PORT);
|
||||
udp_send(trap_msg.pcb, p);
|
||||
/** disassociate remote address and port with this pcb */
|
||||
udp_disconnect(trap_msg.pcb);
|
||||
/** send to the TRAP destination */
|
||||
udp_sendto(trap_msg.pcb, p, &trap_msg.dip, SNMP_TRAP_PORT);
|
||||
|
||||
pbuf_free(p);
|
||||
}
|
||||
@@ -435,13 +426,13 @@ snmp_varbind_list_sum(struct snmp_varbind_root *root)
|
||||
switch (vb->value_type)
|
||||
{
|
||||
case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG):
|
||||
sint_ptr = vb->value;
|
||||
sint_ptr = (s32_t*)vb->value;
|
||||
snmp_asn1_enc_s32t_cnt(*sint_ptr, &vb->vlen);
|
||||
break;
|
||||
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER):
|
||||
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE):
|
||||
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS):
|
||||
uint_ptr = vb->value;
|
||||
uint_ptr = (u32_t*)vb->value;
|
||||
snmp_asn1_enc_u32t_cnt(*uint_ptr, &vb->vlen);
|
||||
break;
|
||||
case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR):
|
||||
@@ -451,7 +442,7 @@ snmp_varbind_list_sum(struct snmp_varbind_root *root)
|
||||
vb->vlen = vb->value_len;
|
||||
break;
|
||||
case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID):
|
||||
sint_ptr = vb->value;
|
||||
sint_ptr = (s32_t*)vb->value;
|
||||
snmp_asn1_enc_oid_cnt(vb->value_len / sizeof(s32_t), sint_ptr, &vb->vlen);
|
||||
break;
|
||||
default:
|
||||
@@ -649,25 +640,25 @@ snmp_varbind_list_enc(struct snmp_varbind_root *root, struct pbuf *p, u16_t ofs)
|
||||
switch (vb->value_type)
|
||||
{
|
||||
case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG):
|
||||
sint_ptr = vb->value;
|
||||
sint_ptr = (s32_t*)vb->value;
|
||||
snmp_asn1_enc_s32t(p, ofs, vb->vlen, *sint_ptr);
|
||||
break;
|
||||
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER):
|
||||
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE):
|
||||
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS):
|
||||
uint_ptr = vb->value;
|
||||
uint_ptr = (u32_t*)vb->value;
|
||||
snmp_asn1_enc_u32t(p, ofs, vb->vlen, *uint_ptr);
|
||||
break;
|
||||
case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR):
|
||||
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR):
|
||||
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE):
|
||||
raw_ptr = vb->value;
|
||||
raw_ptr = (u8_t*)vb->value;
|
||||
snmp_asn1_enc_raw(p, ofs, vb->vlen, raw_ptr);
|
||||
break;
|
||||
case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL):
|
||||
break;
|
||||
case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID):
|
||||
sint_ptr = vb->value;
|
||||
sint_ptr = (s32_t*)vb->value;
|
||||
snmp_asn1_enc_oid(p, ofs, vb->value_len / sizeof(s32_t), sint_ptr);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -48,9 +48,28 @@
|
||||
|
||||
struct stats_ lwip_stats;
|
||||
|
||||
void stats_init(void)
|
||||
{
|
||||
#ifdef LWIP_DEBUG
|
||||
#if MEMP_STATS
|
||||
const char * memp_names[] = {
|
||||
#define LWIP_MEMPOOL(name,num,size,desc) desc,
|
||||
#include "lwip/memp_std.h"
|
||||
};
|
||||
int i;
|
||||
for (i = 0; i < MEMP_MAX; i++) {
|
||||
lwip_stats.memp[i].name = memp_names[i];
|
||||
}
|
||||
#endif /* MEMP_STATS */
|
||||
#if MEM_STATS
|
||||
lwip_stats.mem.name = "MEM";
|
||||
#endif /* MEM_STATS */
|
||||
#endif /* LWIP_DEBUG */
|
||||
}
|
||||
|
||||
#if LWIP_STATS_DISPLAY
|
||||
void
|
||||
stats_display_proto(struct stats_proto *proto, char *name)
|
||||
stats_display_proto(struct stats_proto *proto, const char *name)
|
||||
{
|
||||
LWIP_PLATFORM_DIAG(("\n%s\n\t", name));
|
||||
LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", proto->xmit));
|
||||
@@ -72,21 +91,26 @@ void
|
||||
stats_display_igmp(struct stats_igmp *igmp)
|
||||
{
|
||||
LWIP_PLATFORM_DIAG(("\nIGMP\n\t"));
|
||||
LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", igmp->lenerr));
|
||||
LWIP_PLATFORM_DIAG(("xmit: %"STAT_COUNTER_F"\n\t", igmp->xmit));
|
||||
LWIP_PLATFORM_DIAG(("recv: %"STAT_COUNTER_F"\n\t", igmp->recv));
|
||||
LWIP_PLATFORM_DIAG(("drop: %"STAT_COUNTER_F"\n\t", igmp->drop));
|
||||
LWIP_PLATFORM_DIAG(("chkerr: %"STAT_COUNTER_F"\n\t", igmp->chkerr));
|
||||
LWIP_PLATFORM_DIAG(("v1_rxed: %"STAT_COUNTER_F"\n\t", igmp->v1_rxed));
|
||||
LWIP_PLATFORM_DIAG(("join_sent: %"STAT_COUNTER_F"\n\t", igmp->join_sent));
|
||||
LWIP_PLATFORM_DIAG(("leave_sent: %"STAT_COUNTER_F"\n\t", igmp->leave_sent));
|
||||
LWIP_PLATFORM_DIAG(("unicast_query: %"STAT_COUNTER_F"\n\t", igmp->unicast_query));
|
||||
LWIP_PLATFORM_DIAG(("report_sent: %"STAT_COUNTER_F"\n\t", igmp->report_sent));
|
||||
LWIP_PLATFORM_DIAG(("report_rxed: %"STAT_COUNTER_F"\n\t", igmp->report_rxed));
|
||||
LWIP_PLATFORM_DIAG(("group_query_rxed: %"STAT_COUNTER_F"\n", igmp->group_query_rxed));
|
||||
LWIP_PLATFORM_DIAG(("lenerr: %"STAT_COUNTER_F"\n\t", igmp->lenerr));
|
||||
LWIP_PLATFORM_DIAG(("memerr: %"STAT_COUNTER_F"\n\t", igmp->memerr));
|
||||
LWIP_PLATFORM_DIAG(("proterr: %"STAT_COUNTER_F"\n\t", igmp->proterr));
|
||||
LWIP_PLATFORM_DIAG(("rx_v1: %"STAT_COUNTER_F"\n\t", igmp->rx_v1));
|
||||
LWIP_PLATFORM_DIAG(("rx_group: %"STAT_COUNTER_F"\n", igmp->rx_group));
|
||||
LWIP_PLATFORM_DIAG(("rx_general: %"STAT_COUNTER_F"\n", igmp->rx_general));
|
||||
LWIP_PLATFORM_DIAG(("rx_report: %"STAT_COUNTER_F"\n\t", igmp->rx_report));
|
||||
LWIP_PLATFORM_DIAG(("tx_join: %"STAT_COUNTER_F"\n\t", igmp->tx_join));
|
||||
LWIP_PLATFORM_DIAG(("tx_leave: %"STAT_COUNTER_F"\n\t", igmp->tx_leave));
|
||||
LWIP_PLATFORM_DIAG(("tx_report: %"STAT_COUNTER_F"\n\t", igmp->tx_report));
|
||||
}
|
||||
#endif /* IGMP_STATS */
|
||||
|
||||
#if MEM_STATS || MEMP_STATS
|
||||
void
|
||||
stats_display_mem(struct stats_mem *mem, char *name)
|
||||
stats_display_mem(struct stats_mem *mem, const char *name)
|
||||
{
|
||||
LWIP_PLATFORM_DIAG(("\nMEM %s\n\t", name));
|
||||
LWIP_PLATFORM_DIAG(("avail: %"U32_F"\n\t", (u32_t)mem->avail));
|
||||
@@ -115,12 +139,15 @@ void
|
||||
stats_display_sys(struct stats_sys *sys)
|
||||
{
|
||||
LWIP_PLATFORM_DIAG(("\nSYS\n\t"));
|
||||
LWIP_PLATFORM_DIAG(("sem.used: %"U32_F"\n\t", (u32_t)sys->sem.used));
|
||||
LWIP_PLATFORM_DIAG(("sem.max: %"U32_F"\n\t", (u32_t)sys->sem.max));
|
||||
LWIP_PLATFORM_DIAG(("sem.err: %"U32_F"\n\t", (u32_t)sys->sem.err));
|
||||
LWIP_PLATFORM_DIAG(("mbox.used: %"U32_F"\n\t", (u32_t)sys->mbox.used));
|
||||
LWIP_PLATFORM_DIAG(("mbox.max: %"U32_F"\n\t", (u32_t)sys->mbox.max));
|
||||
LWIP_PLATFORM_DIAG(("mbox.err: %"U32_F"\n\t", (u32_t)sys->mbox.err));
|
||||
LWIP_PLATFORM_DIAG(("sem.used: %"U32_F"\n\t", (u32_t)sys->sem.used));
|
||||
LWIP_PLATFORM_DIAG(("sem.max: %"U32_F"\n\t", (u32_t)sys->sem.max));
|
||||
LWIP_PLATFORM_DIAG(("sem.err: %"U32_F"\n\t", (u32_t)sys->sem.err));
|
||||
LWIP_PLATFORM_DIAG(("mutex.used: %"U32_F"\n\t", (u32_t)sys->mutex.used));
|
||||
LWIP_PLATFORM_DIAG(("mutex.max: %"U32_F"\n\t", (u32_t)sys->mutex.max));
|
||||
LWIP_PLATFORM_DIAG(("mutex.err: %"U32_F"\n\t", (u32_t)sys->mutex.err));
|
||||
LWIP_PLATFORM_DIAG(("mbox.used: %"U32_F"\n\t", (u32_t)sys->mbox.used));
|
||||
LWIP_PLATFORM_DIAG(("mbox.max: %"U32_F"\n\t", (u32_t)sys->mbox.max));
|
||||
LWIP_PLATFORM_DIAG(("mbox.err: %"U32_F"\n\t", (u32_t)sys->mbox.err));
|
||||
}
|
||||
#endif /* SYS_STATS */
|
||||
|
||||
|
||||
312
src/core/sys.c
312
src/core/sys.c
@@ -38,309 +38,31 @@
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if (NO_SYS == 0) /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/tcpip.h"
|
||||
|
||||
/* Most of the functions defined in sys.h must be implemented in the
|
||||
* architecture-dependent file sys_arch.c */
|
||||
|
||||
#if !NO_SYS
|
||||
|
||||
#ifndef sys_msleep
|
||||
/**
|
||||
* Struct used for sys_sem_wait_timeout() to tell wether the time
|
||||
* has run out or the semaphore has really become available.
|
||||
*/
|
||||
struct sswt_cb
|
||||
{
|
||||
s16_t timeflag;
|
||||
sys_sem_t *psem;
|
||||
};
|
||||
|
||||
/**
|
||||
* Wait (forever) for a message to arrive in an mbox.
|
||||
* While waiting, timeouts (for this thread) are processed.
|
||||
*
|
||||
* @param mbox the mbox to fetch the message from
|
||||
* @param msg the place to store the message
|
||||
*/
|
||||
void
|
||||
sys_mbox_fetch(sys_mbox_t mbox, void **msg)
|
||||
{
|
||||
u32_t time_needed;
|
||||
struct sys_timeouts *timeouts;
|
||||
struct sys_timeo *tmptimeout;
|
||||
sys_timeout_handler h;
|
||||
void *arg;
|
||||
|
||||
again:
|
||||
timeouts = sys_arch_timeouts();
|
||||
|
||||
if (!timeouts || !timeouts->next) {
|
||||
UNLOCK_TCPIP_CORE();
|
||||
time_needed = sys_arch_mbox_fetch(mbox, msg, 0);
|
||||
LOCK_TCPIP_CORE();
|
||||
} else {
|
||||
if (timeouts->next->time > 0) {
|
||||
UNLOCK_TCPIP_CORE();
|
||||
time_needed = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time);
|
||||
LOCK_TCPIP_CORE();
|
||||
} else {
|
||||
time_needed = SYS_ARCH_TIMEOUT;
|
||||
}
|
||||
|
||||
if (time_needed == SYS_ARCH_TIMEOUT) {
|
||||
/* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
|
||||
could be fetched. We should now call the timeout handler and
|
||||
deallocate the memory allocated for the timeout. */
|
||||
tmptimeout = timeouts->next;
|
||||
timeouts->next = tmptimeout->next;
|
||||
h = tmptimeout->h;
|
||||
arg = tmptimeout->arg;
|
||||
memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
|
||||
if (h != NULL) {
|
||||
LWIP_DEBUGF(SYS_DEBUG, ("smf calling h=%p(%p)\n", *(void**)&h, arg));
|
||||
h(arg);
|
||||
}
|
||||
|
||||
/* We try again to fetch a message from the mbox. */
|
||||
goto again;
|
||||
} else {
|
||||
/* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
|
||||
occured. The time variable is set to the number of
|
||||
milliseconds we waited for the message. */
|
||||
if (time_needed < timeouts->next->time) {
|
||||
timeouts->next->time -= time_needed;
|
||||
} else {
|
||||
timeouts->next->time = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait (forever) for a semaphore to become available.
|
||||
* While waiting, timeouts (for this thread) are processed.
|
||||
*
|
||||
* @param sem semaphore to wait for
|
||||
*/
|
||||
void
|
||||
sys_sem_wait(sys_sem_t sem)
|
||||
{
|
||||
u32_t time_needed;
|
||||
struct sys_timeouts *timeouts;
|
||||
struct sys_timeo *tmptimeout;
|
||||
sys_timeout_handler h;
|
||||
void *arg;
|
||||
|
||||
again:
|
||||
|
||||
timeouts = sys_arch_timeouts();
|
||||
|
||||
if (!timeouts || !timeouts->next) {
|
||||
sys_arch_sem_wait(sem, 0);
|
||||
} else {
|
||||
if (timeouts->next->time > 0) {
|
||||
time_needed = sys_arch_sem_wait(sem, timeouts->next->time);
|
||||
} else {
|
||||
time_needed = SYS_ARCH_TIMEOUT;
|
||||
}
|
||||
|
||||
if (time_needed == SYS_ARCH_TIMEOUT) {
|
||||
/* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
|
||||
could be fetched. We should now call the timeout handler and
|
||||
deallocate the memory allocated for the timeout. */
|
||||
tmptimeout = timeouts->next;
|
||||
timeouts->next = tmptimeout->next;
|
||||
h = tmptimeout->h;
|
||||
arg = tmptimeout->arg;
|
||||
memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
|
||||
if (h != NULL) {
|
||||
LWIP_DEBUGF(SYS_DEBUG, ("ssw h=%p(%p)\n", *(void**)&h, (void *)arg));
|
||||
h(arg);
|
||||
}
|
||||
|
||||
/* We try again to fetch a message from the mbox. */
|
||||
goto again;
|
||||
} else {
|
||||
/* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
|
||||
occured. The time variable is set to the number of
|
||||
milliseconds we waited for the message. */
|
||||
if (time_needed < timeouts->next->time) {
|
||||
timeouts->next->time -= time_needed;
|
||||
} else {
|
||||
timeouts->next->time = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a one-shot timer (aka timeout). Timeouts are processed in the
|
||||
* following cases:
|
||||
* - while waiting for a message using sys_mbox_fetch()
|
||||
* - while waiting for a semaphore using sys_sem_wait() or sys_sem_wait_timeout()
|
||||
* - while sleeping using the inbuilt sys_msleep()
|
||||
*
|
||||
* @param msecs time in milliseconds after that the timer should expire
|
||||
* @param h callback function to call when msecs have elapsed
|
||||
* @param arg argument to pass to the callback function
|
||||
*/
|
||||
void
|
||||
sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
|
||||
{
|
||||
struct sys_timeouts *timeouts;
|
||||
struct sys_timeo *timeout, *t;
|
||||
|
||||
timeout = memp_malloc(MEMP_SYS_TIMEOUT);
|
||||
if (timeout == NULL) {
|
||||
LWIP_ASSERT("sys_timeout: timeout != NULL", timeout != NULL);
|
||||
return;
|
||||
}
|
||||
timeout->next = NULL;
|
||||
timeout->h = h;
|
||||
timeout->arg = arg;
|
||||
timeout->time = msecs;
|
||||
|
||||
timeouts = sys_arch_timeouts();
|
||||
|
||||
LWIP_DEBUGF(SYS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" h=%p arg=%p\n",
|
||||
(void *)timeout, msecs, *(void**)&h, (void *)arg));
|
||||
|
||||
if (timeouts == NULL) {
|
||||
LWIP_ASSERT("sys_timeout: timeouts != NULL", timeouts != NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (timeouts->next == NULL) {
|
||||
timeouts->next = timeout;
|
||||
return;
|
||||
}
|
||||
|
||||
if (timeouts->next->time > msecs) {
|
||||
timeouts->next->time -= msecs;
|
||||
timeout->next = timeouts->next;
|
||||
timeouts->next = timeout;
|
||||
} else {
|
||||
for(t = timeouts->next; t != NULL; t = t->next) {
|
||||
timeout->time -= t->time;
|
||||
if (t->next == NULL || t->next->time > timeout->time) {
|
||||
if (t->next != NULL) {
|
||||
t->next->time -= timeout->time;
|
||||
}
|
||||
timeout->next = t->next;
|
||||
t->next = timeout;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Go through timeout list (for this task only) and remove the first matching
|
||||
* entry, even though the timeout has not triggered yet.
|
||||
*
|
||||
* @note This function only works as expected if there is only one timeout
|
||||
* calling 'h' in the list of timeouts.
|
||||
*
|
||||
* @param h callback function that would be called by the timeout
|
||||
* @param arg callback argument that would be passed to h
|
||||
*/
|
||||
void
|
||||
sys_untimeout(sys_timeout_handler h, void *arg)
|
||||
{
|
||||
struct sys_timeouts *timeouts;
|
||||
struct sys_timeo *prev_t, *t;
|
||||
|
||||
timeouts = sys_arch_timeouts();
|
||||
|
||||
if (timeouts == NULL) {
|
||||
LWIP_ASSERT("sys_untimeout: timeouts != NULL", timeouts != NULL);
|
||||
return;
|
||||
}
|
||||
if (timeouts->next == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (t = timeouts->next, prev_t = NULL; t != NULL; prev_t = t, t = t->next) {
|
||||
if ((t->h == h) && (t->arg == arg)) {
|
||||
/* We have a match */
|
||||
/* Unlink from previous in list */
|
||||
if (prev_t == NULL) {
|
||||
timeouts->next = t->next;
|
||||
} else {
|
||||
prev_t->next = t->next;
|
||||
}
|
||||
/* If not the last one, add time of this one back to next */
|
||||
if (t->next != NULL) {
|
||||
t->next->time += t->time;
|
||||
}
|
||||
memp_free(MEMP_SYS_TIMEOUT, t);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Timeout handler function for sys_sem_wait_timeout()
|
||||
*
|
||||
* @param arg struct sswt_cb* used to signal a semaphore and end waiting.
|
||||
*/
|
||||
static void
|
||||
sswt_handler(void *arg)
|
||||
{
|
||||
struct sswt_cb *sswt_cb = (struct sswt_cb *) arg;
|
||||
|
||||
/* Timeout. Set flag to TRUE and signal semaphore */
|
||||
sswt_cb->timeflag = 1;
|
||||
sys_sem_signal(*(sswt_cb->psem));
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for a semaphore with timeout (specified in ms)
|
||||
*
|
||||
* @param sem semaphore to wait
|
||||
* @param timeout timeout in ms (0: wait forever)
|
||||
* @return 0 on timeout, 1 otherwise
|
||||
*/
|
||||
int
|
||||
sys_sem_wait_timeout(sys_sem_t sem, u32_t timeout)
|
||||
{
|
||||
struct sswt_cb sswt_cb;
|
||||
|
||||
sswt_cb.psem = &sem;
|
||||
sswt_cb.timeflag = 0;
|
||||
|
||||
/* If timeout is zero, then just wait forever */
|
||||
if (timeout > 0) {
|
||||
/* Create a timer and pass it the address of our flag */
|
||||
sys_timeout(timeout, sswt_handler, &sswt_cb);
|
||||
}
|
||||
sys_sem_wait(sem);
|
||||
/* Was it a timeout? */
|
||||
if (sswt_cb.timeflag) {
|
||||
/* timeout */
|
||||
return 0;
|
||||
} else {
|
||||
/* Not a timeout. Remove timeout entry */
|
||||
sys_untimeout(sswt_handler, &sswt_cb);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sleep for some ms. Timeouts are processed while sleeping.
|
||||
* Sleep for some ms. Timeouts are NOT processed while sleeping.
|
||||
*
|
||||
* @param ms number of milliseconds to sleep
|
||||
*/
|
||||
void
|
||||
sys_msleep(u32_t ms)
|
||||
{
|
||||
sys_sem_t delaysem = sys_sem_new(0);
|
||||
|
||||
sys_sem_wait_timeout(delaysem, ms);
|
||||
|
||||
sys_sem_free(delaysem);
|
||||
if (ms > 0) {
|
||||
sys_sem_t delaysem;
|
||||
err_t err = sys_sem_new(&delaysem, 0);
|
||||
if (err == ERR_OK) {
|
||||
sys_arch_sem_wait(&delaysem, ms);
|
||||
sys_sem_free(&delaysem);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* sys_msleep */
|
||||
|
||||
|
||||
#endif /* NO_SYS */
|
||||
#endif /* !NO_SYS */
|
||||
|
||||
737
src/core/tcp.c
737
src/core/tcp.c
File diff suppressed because it is too large
Load Diff
@@ -45,13 +45,12 @@
|
||||
|
||||
#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/tcp_impl.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/snmp.h"
|
||||
@@ -94,6 +93,10 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
struct tcp_pcb *pcb, *prev;
|
||||
struct tcp_pcb_listen *lpcb;
|
||||
#if SO_REUSE
|
||||
struct tcp_pcb *lpcb_prev = NULL;
|
||||
struct tcp_pcb_listen *lpcb_any = NULL;
|
||||
#endif /* SO_REUSE */
|
||||
u8_t hdrlen;
|
||||
err_t err;
|
||||
|
||||
@@ -102,7 +105,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
TCP_STATS_INC(tcp.recv);
|
||||
snmp_inc_tcpinsegs();
|
||||
|
||||
iphdr = p->payload;
|
||||
iphdr = (struct ip_hdr *)p->payload;
|
||||
tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
|
||||
|
||||
#if TCP_INPUT_DEBUG
|
||||
@@ -114,38 +117,28 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
/* drop short packets */
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len));
|
||||
TCP_STATS_INC(tcp.lenerr);
|
||||
TCP_STATS_INC(tcp.drop);
|
||||
snmp_inc_tcpinerrs();
|
||||
pbuf_free(p);
|
||||
return;
|
||||
goto dropped;
|
||||
}
|
||||
|
||||
/* Don't even process incoming broadcasts/multicasts. */
|
||||
if (ip_addr_isbroadcast(&(iphdr->dest), inp) ||
|
||||
ip_addr_ismulticast(&(iphdr->dest))) {
|
||||
if (ip_addr_isbroadcast(¤t_iphdr_dest, inp) ||
|
||||
ip_addr_ismulticast(¤t_iphdr_dest)) {
|
||||
TCP_STATS_INC(tcp.proterr);
|
||||
TCP_STATS_INC(tcp.drop);
|
||||
snmp_inc_tcpinerrs();
|
||||
pbuf_free(p);
|
||||
return;
|
||||
goto dropped;
|
||||
}
|
||||
|
||||
#if CHECKSUM_CHECK_TCP
|
||||
/* Verify TCP checksum. */
|
||||
if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
|
||||
(struct ip_addr *)&(iphdr->dest),
|
||||
if (inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(),
|
||||
IP_PROTO_TCP, p->tot_len) != 0) {
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n",
|
||||
inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src), (struct ip_addr *)&(iphdr->dest),
|
||||
inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(),
|
||||
IP_PROTO_TCP, p->tot_len)));
|
||||
#if TCP_DEBUG
|
||||
tcp_debug_print(tcphdr);
|
||||
#endif /* TCP_DEBUG */
|
||||
TCP_STATS_INC(tcp.chkerr);
|
||||
TCP_STATS_INC(tcp.drop);
|
||||
snmp_inc_tcpinerrs();
|
||||
pbuf_free(p);
|
||||
return;
|
||||
goto dropped;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -156,10 +149,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
/* drop short packets */
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet\n"));
|
||||
TCP_STATS_INC(tcp.lenerr);
|
||||
TCP_STATS_INC(tcp.drop);
|
||||
snmp_inc_tcpinerrs();
|
||||
pbuf_free(p);
|
||||
return;
|
||||
goto dropped;
|
||||
}
|
||||
|
||||
/* Convert fields in TCP header to host byte order. */
|
||||
@@ -183,8 +173,8 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
|
||||
if (pcb->remote_port == tcphdr->src &&
|
||||
pcb->local_port == tcphdr->dest &&
|
||||
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
|
||||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
|
||||
ip_addr_cmp(&(pcb->remote_ip), ¤t_iphdr_src) &&
|
||||
ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest)) {
|
||||
|
||||
/* Move this PCB to the front of the list so that subsequent
|
||||
lookups will be faster (we exploit locality in TCP segment
|
||||
@@ -208,8 +198,8 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT);
|
||||
if (pcb->remote_port == tcphdr->src &&
|
||||
pcb->local_port == tcphdr->dest &&
|
||||
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
|
||||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
|
||||
ip_addr_cmp(&(pcb->remote_ip), ¤t_iphdr_src) &&
|
||||
ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest)) {
|
||||
/* We don't really care enough to move this PCB to the front
|
||||
of the list since we are not very likely to receive that
|
||||
many segments for connections in TIME-WAIT. */
|
||||
@@ -220,31 +210,55 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally, if we still did not get a match, we check all PCBs that
|
||||
are LISTENing for incoming connections. */
|
||||
/* Finally, if we still did not get a match, we check all PCBs that
|
||||
are LISTENing for incoming connections. */
|
||||
prev = NULL;
|
||||
for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
|
||||
if ((ip_addr_isany(&(lpcb->local_ip)) ||
|
||||
ip_addr_cmp(&(lpcb->local_ip), &(iphdr->dest))) &&
|
||||
lpcb->local_port == tcphdr->dest) {
|
||||
/* Move this PCB to the front of the list so that subsequent
|
||||
lookups will be faster (we exploit locality in TCP segment
|
||||
arrivals). */
|
||||
if (prev != NULL) {
|
||||
((struct tcp_pcb_listen *)prev)->next = lpcb->next;
|
||||
/* our successor is the remainder of the listening list */
|
||||
lpcb->next = tcp_listen_pcbs.listen_pcbs;
|
||||
/* put this listening pcb at the head of the listening list */
|
||||
tcp_listen_pcbs.listen_pcbs = lpcb;
|
||||
if (lpcb->local_port == tcphdr->dest) {
|
||||
#if SO_REUSE
|
||||
if (ip_addr_cmp(&(lpcb->local_ip), ¤t_iphdr_dest)) {
|
||||
/* found an exact match */
|
||||
break;
|
||||
} else if(ip_addr_isany(&(lpcb->local_ip))) {
|
||||
/* found an ANY-match */
|
||||
lpcb_any = lpcb;
|
||||
lpcb_prev = prev;
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
|
||||
tcp_listen_input(lpcb);
|
||||
pbuf_free(p);
|
||||
return;
|
||||
#else /* SO_REUSE */
|
||||
if (ip_addr_cmp(&(lpcb->local_ip), ¤t_iphdr_dest) ||
|
||||
ip_addr_isany(&(lpcb->local_ip))) {
|
||||
/* found a match */
|
||||
break;
|
||||
}
|
||||
#endif /* SO_REUSE */
|
||||
}
|
||||
prev = (struct tcp_pcb *)lpcb;
|
||||
}
|
||||
#if SO_REUSE
|
||||
/* first try specific local IP */
|
||||
if (lpcb == NULL) {
|
||||
/* only pass to ANY if no specific local IP has been found */
|
||||
lpcb = lpcb_any;
|
||||
prev = lpcb_prev;
|
||||
}
|
||||
#endif /* SO_REUSE */
|
||||
if (lpcb != NULL) {
|
||||
/* Move this PCB to the front of the list so that subsequent
|
||||
lookups will be faster (we exploit locality in TCP segment
|
||||
arrivals). */
|
||||
if (prev != NULL) {
|
||||
((struct tcp_pcb_listen *)prev)->next = lpcb->next;
|
||||
/* our successor is the remainder of the listening list */
|
||||
lpcb->next = tcp_listen_pcbs.listen_pcbs;
|
||||
/* put this listening pcb at the head of the listening list */
|
||||
tcp_listen_pcbs.listen_pcbs = lpcb;
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n"));
|
||||
tcp_listen_input(lpcb);
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#if TCP_INPUT_DEBUG
|
||||
@@ -265,27 +279,25 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
/* Set up a tcp_seg structure. */
|
||||
inseg.next = NULL;
|
||||
inseg.len = p->tot_len;
|
||||
inseg.dataptr = p->payload;
|
||||
inseg.p = p;
|
||||
inseg.tcphdr = tcphdr;
|
||||
|
||||
recv_data = NULL;
|
||||
recv_flags = 0;
|
||||
|
||||
if (flags & TCP_PSH) {
|
||||
p->flags |= PBUF_FLAG_PUSH;
|
||||
}
|
||||
|
||||
/* If there is data which was previously "refused" by upper layer */
|
||||
if (pcb->refused_data != NULL) {
|
||||
/* Notify again application with data previously received. */
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n"));
|
||||
TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err);
|
||||
if (err == ERR_OK) {
|
||||
pcb->refused_data = NULL;
|
||||
} else {
|
||||
/* drop incoming packets, because pcb is "full" */
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n"));
|
||||
if ((tcp_process_refused_data(pcb) == ERR_ABRT) ||
|
||||
((pcb->refused_data != NULL) && (tcplen > 0))) {
|
||||
/* pcb has been aborted or refused data is still refused and the new
|
||||
segment contains data */
|
||||
TCP_STATS_INC(tcp.drop);
|
||||
snmp_inc_tcpinerrs();
|
||||
pbuf_free(p);
|
||||
return;
|
||||
goto aborted;
|
||||
}
|
||||
}
|
||||
tcp_input_pcb = pcb;
|
||||
@@ -304,6 +316,12 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
} else if (recv_flags & TF_CLOSED) {
|
||||
/* The connection has been closed and we will deallocate the
|
||||
PCB. */
|
||||
if (!(pcb->flags & TF_RXCLOSED)) {
|
||||
/* Connection closed although the application has only shut down the
|
||||
tx side: call the PCB's err callback and indicate the closure to
|
||||
ensure the application doesn't continue using the PCB. */
|
||||
TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_CLSD);
|
||||
}
|
||||
tcp_pcb_remove(&tcp_active_pcbs, pcb);
|
||||
memp_free(MEMP_TCP_PCB, pcb);
|
||||
} else {
|
||||
@@ -313,15 +331,26 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
now. */
|
||||
if (pcb->acked > 0) {
|
||||
TCP_EVENT_SENT(pcb, pcb->acked, err);
|
||||
if (err == ERR_ABRT) {
|
||||
goto aborted;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (recv_data != NULL) {
|
||||
if(flags & TCP_PSH) {
|
||||
recv_data->flags |= PBUF_FLAG_PUSH;
|
||||
LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL);
|
||||
if (pcb->flags & TF_RXCLOSED) {
|
||||
/* received data although already closed -> abort (send RST) to
|
||||
notify the remote host that not all data has been processed */
|
||||
pbuf_free(recv_data);
|
||||
tcp_abort(pcb);
|
||||
goto aborted;
|
||||
}
|
||||
|
||||
/* Notify application that data has been received. */
|
||||
TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err);
|
||||
if (err == ERR_ABRT) {
|
||||
goto aborted;
|
||||
}
|
||||
|
||||
/* If the upper layer can't receive this data, store it */
|
||||
if (err != ERR_OK) {
|
||||
@@ -333,7 +362,20 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
/* If a FIN segment was received, we call the callback
|
||||
function with a NULL buffer to indicate EOF. */
|
||||
if (recv_flags & TF_GOT_FIN) {
|
||||
TCP_EVENT_RECV(pcb, NULL, ERR_OK, err);
|
||||
if (pcb->refused_data != NULL) {
|
||||
/* Delay this if we have refused data. */
|
||||
pcb->refused_data->flags |= PBUF_FLAG_TCP_FIN;
|
||||
} else {
|
||||
/* correct rcv_wnd as the application won't call tcp_recved()
|
||||
for the FIN's seqno */
|
||||
if (pcb->rcv_wnd != TCP_WND) {
|
||||
pcb->rcv_wnd++;
|
||||
}
|
||||
TCP_EVENT_CLOSED(pcb, err);
|
||||
if (err == ERR_ABRT) {
|
||||
goto aborted;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tcp_input_pcb = NULL;
|
||||
@@ -346,8 +388,11 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
#endif /* TCP_INPUT_DEBUG */
|
||||
}
|
||||
}
|
||||
/* Jump target if pcb has been aborted in a callback (by calling tcp_abort()).
|
||||
Below this line, 'pcb' may not be dereferenced! */
|
||||
aborted:
|
||||
tcp_input_pcb = NULL;
|
||||
|
||||
recv_data = NULL;
|
||||
|
||||
/* give up our reference to inseg.p */
|
||||
if (inseg.p != NULL)
|
||||
@@ -364,7 +409,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
TCP_STATS_INC(tcp.proterr);
|
||||
TCP_STATS_INC(tcp.drop);
|
||||
tcp_rst(ackno, seqno + tcplen,
|
||||
&(iphdr->dest), &(iphdr->src),
|
||||
ip_current_dest_addr(), ip_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
}
|
||||
pbuf_free(p);
|
||||
@@ -372,6 +417,11 @@ tcp_input(struct pbuf *p, struct netif *inp)
|
||||
|
||||
LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
|
||||
PERF_STOP("tcp_input");
|
||||
return;
|
||||
dropped:
|
||||
TCP_STATS_INC(tcp.drop);
|
||||
snmp_inc_tcpinerrs();
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -392,15 +442,19 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
||||
struct tcp_pcb *npcb;
|
||||
err_t rc;
|
||||
|
||||
if (flags & TCP_RST) {
|
||||
/* An incoming RST should be ignored. Return. */
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/* In the LISTEN state, we check for incoming SYN segments,
|
||||
creates a new PCB, and responds with a SYN|ACK. */
|
||||
if (flags & TCP_ACK) {
|
||||
/* For incoming segments with the ACK flag set, respond with a
|
||||
RST. */
|
||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_listen_input: ACK in LISTEN, sending reset\n"));
|
||||
tcp_rst(ackno + 1, seqno + tcplen,
|
||||
&(iphdr->dest), &(iphdr->src),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(),
|
||||
ip_current_src_addr(), tcphdr->dest, tcphdr->src);
|
||||
} else if (flags & TCP_SYN) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection request %"U16_F" -> %"U16_F".\n", tcphdr->src, tcphdr->dest));
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
@@ -422,14 +476,15 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
||||
pcb->accepts_pending++;
|
||||
#endif /* TCP_LISTEN_BACKLOG */
|
||||
/* Set up the new PCB. */
|
||||
ip_addr_set(&(npcb->local_ip), &(iphdr->dest));
|
||||
ip_addr_copy(npcb->local_ip, current_iphdr_dest);
|
||||
npcb->local_port = pcb->local_port;
|
||||
ip_addr_set(&(npcb->remote_ip), &(iphdr->src));
|
||||
ip_addr_copy(npcb->remote_ip, current_iphdr_src);
|
||||
npcb->remote_port = tcphdr->src;
|
||||
npcb->state = SYN_RCVD;
|
||||
npcb->rcv_nxt = seqno + 1;
|
||||
npcb->rcv_ann_right_edge = npcb->rcv_nxt;
|
||||
npcb->snd_wnd = tcphdr->wnd;
|
||||
npcb->snd_wnd_max = tcphdr->wnd;
|
||||
npcb->ssthresh = npcb->snd_wnd;
|
||||
npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
|
||||
npcb->callback_arg = pcb->callback_arg;
|
||||
@@ -437,10 +492,10 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
||||
npcb->accept = pcb->accept;
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
/* inherit socket options */
|
||||
npcb->so_options = pcb->so_options & (SOF_DEBUG|SOF_DONTROUTE|SOF_KEEPALIVE|SOF_OOBINLINE|SOF_LINGER);
|
||||
npcb->so_options = pcb->so_options & SOF_INHERITED;
|
||||
/* Register the new PCB so that we can begin receiving segments
|
||||
for it. */
|
||||
TCP_REG(&tcp_active_pcbs, npcb);
|
||||
TCP_REG_ACTIVE(npcb);
|
||||
|
||||
/* Parse any options in the SYN. */
|
||||
tcp_parseopt(npcb);
|
||||
@@ -451,12 +506,7 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
|
||||
snmp_inc_tcppassiveopens();
|
||||
|
||||
/* Send a SYN|ACK together with the MSS option. */
|
||||
rc = tcp_enqueue(npcb, NULL, 0, TCP_SYN | TCP_ACK, 0, TF_SEG_OPTS_MSS
|
||||
#if LWIP_TCP_TIMESTAMPS
|
||||
/* and maybe include the TIMESTAMP option */
|
||||
| (npcb->flags & TF_TIMESTAMP ? TF_SEG_OPTS_TS : 0)
|
||||
#endif
|
||||
);
|
||||
rc = tcp_enqueue_flags(npcb, TCP_SYN | TCP_ACK);
|
||||
if (rc != ERR_OK) {
|
||||
tcp_abandon(npcb, 0);
|
||||
return rc;
|
||||
@@ -492,7 +542,7 @@ tcp_timewait_input(struct tcp_pcb *pcb)
|
||||
should be sent in reply */
|
||||
if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt+pcb->rcv_wnd)) {
|
||||
/* If the SYN is in the window it is an error, send a reset */
|
||||
tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
|
||||
tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
return ERR_OK;
|
||||
}
|
||||
@@ -565,8 +615,10 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/* Update the PCB (in)activity timer. */
|
||||
pcb->tmr = tcp_ticks;
|
||||
if ((pcb->flags & TF_RXCLOSED) == 0) {
|
||||
/* Update the PCB (in)activity timer unless rx is closed (see tcp_shutdown) */
|
||||
pcb->tmr = tcp_ticks;
|
||||
}
|
||||
pcb->keep_cnt_sent = 0;
|
||||
|
||||
tcp_parseopt(pcb);
|
||||
@@ -584,6 +636,7 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
pcb->rcv_ann_right_edge = pcb->rcv_nxt;
|
||||
pcb->lastack = ackno;
|
||||
pcb->snd_wnd = tcphdr->wnd;
|
||||
pcb->snd_wnd_max = tcphdr->wnd;
|
||||
pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */
|
||||
pcb->state = ESTABLISHED;
|
||||
|
||||
@@ -601,6 +654,7 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_process: SYN-SENT --queuelen %"U16_F"\n", (u16_t)pcb->snd_queuelen));
|
||||
rseg = pcb->unacked;
|
||||
pcb->unacked = rseg->next;
|
||||
tcp_seg_free(rseg);
|
||||
|
||||
/* If there's nothing left to acknowledge, stop the retransmit
|
||||
timer, otherwise reset it to start again */
|
||||
@@ -611,17 +665,18 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
pcb->nrtx = 0;
|
||||
}
|
||||
|
||||
tcp_seg_free(rseg);
|
||||
|
||||
/* Call the user specified function to call when sucessfully
|
||||
* connected. */
|
||||
TCP_EVENT_CONNECTED(pcb, ERR_OK, err);
|
||||
if (err == ERR_ABRT) {
|
||||
return ERR_ABRT;
|
||||
}
|
||||
tcp_ack_now(pcb);
|
||||
}
|
||||
/* received ACK? possibly a half-open connection */
|
||||
else if (flags & TCP_ACK) {
|
||||
/* send a RST to bring the other side in a non-synchronized state. */
|
||||
tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
|
||||
tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
}
|
||||
break;
|
||||
@@ -640,7 +695,10 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
if (err != ERR_OK) {
|
||||
/* If the accept function returns with an error, we abort
|
||||
* the connection. */
|
||||
tcp_abort(pcb);
|
||||
/* Already aborted? */
|
||||
if (err != ERR_ABRT) {
|
||||
tcp_abort(pcb);
|
||||
}
|
||||
return ERR_ABRT;
|
||||
}
|
||||
old_cwnd = pcb->cwnd;
|
||||
@@ -659,11 +717,9 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
tcp_ack_now(pcb);
|
||||
pcb->state = CLOSE_WAIT;
|
||||
}
|
||||
}
|
||||
/* incorrect ACK number */
|
||||
else {
|
||||
/* send RST */
|
||||
tcp_rst(ackno, seqno + tcplen, &(iphdr->dest), &(iphdr->src),
|
||||
} else {
|
||||
/* incorrect ACK number, send RST */
|
||||
tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(), ip_current_src_addr(),
|
||||
tcphdr->dest, tcphdr->src);
|
||||
}
|
||||
} else if ((flags & TCP_SYN) && (seqno == pcb->rcv_nxt - 1)) {
|
||||
@@ -688,7 +744,7 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
||||
tcp_ack_now(pcb);
|
||||
tcp_pcb_purge(pcb);
|
||||
TCP_RMV(&tcp_active_pcbs, pcb);
|
||||
TCP_RMV_ACTIVE(pcb);
|
||||
pcb->state = TIME_WAIT;
|
||||
TCP_REG(&tcp_tw_pcbs, pcb);
|
||||
} else {
|
||||
@@ -705,7 +761,7 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: FIN_WAIT_2 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
||||
tcp_ack_now(pcb);
|
||||
tcp_pcb_purge(pcb);
|
||||
TCP_RMV(&tcp_active_pcbs, pcb);
|
||||
TCP_RMV_ACTIVE(pcb);
|
||||
pcb->state = TIME_WAIT;
|
||||
TCP_REG(&tcp_tw_pcbs, pcb);
|
||||
}
|
||||
@@ -715,7 +771,7 @@ tcp_process(struct tcp_pcb *pcb)
|
||||
if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
|
||||
tcp_pcb_purge(pcb);
|
||||
TCP_RMV(&tcp_active_pcbs, pcb);
|
||||
TCP_RMV_ACTIVE(pcb);
|
||||
pcb->state = TIME_WAIT;
|
||||
TCP_REG(&tcp_tw_pcbs, pcb);
|
||||
}
|
||||
@@ -758,7 +814,7 @@ tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next)
|
||||
(next->tcphdr->seqno + next->len))) {
|
||||
/* cseg with FIN already processed */
|
||||
if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
|
||||
TCPH_FLAGS_SET(cseg->tcphdr, TCPH_FLAGS(cseg->tcphdr) | TCP_FIN);
|
||||
TCPH_SET_FLAG(cseg->tcphdr, TCP_FIN);
|
||||
}
|
||||
old_seg = next;
|
||||
next = next->next;
|
||||
@@ -773,14 +829,14 @@ tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next)
|
||||
}
|
||||
cseg->next = next;
|
||||
}
|
||||
#endif
|
||||
#endif /* TCP_QUEUE_OOSEQ */
|
||||
|
||||
/**
|
||||
* Called by tcp_process. Checks if the given segment is an ACK for outstanding
|
||||
* data, and if so frees the memory of the buffered data. Next, is places the
|
||||
* segment on any of the receive queues (pcb->recved or pcb->ooseq). If the segment
|
||||
* is buffered, the pbuf is referenced by pbuf_ref so that it will not be freed until
|
||||
* i it has been removed from the buffer.
|
||||
* it has been removed from the buffer.
|
||||
*
|
||||
* If the incoming segment constitutes an ACK for a segment that was used for RTT
|
||||
* estimation, the RTT is estimated here as well.
|
||||
@@ -793,13 +849,19 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
struct tcp_seg *next;
|
||||
#if TCP_QUEUE_OOSEQ
|
||||
struct tcp_seg *prev, *cseg;
|
||||
#endif
|
||||
#endif /* TCP_QUEUE_OOSEQ */
|
||||
struct pbuf *p;
|
||||
s32_t off;
|
||||
s16_t m;
|
||||
u32_t right_wnd_edge;
|
||||
u16_t new_tot_len;
|
||||
int found_dupack = 0;
|
||||
#if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS
|
||||
u32_t ooseq_blen;
|
||||
u16_t ooseq_qlen;
|
||||
#endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */
|
||||
|
||||
LWIP_ASSERT("tcp_receive: wrong state", pcb->state >= ESTABLISHED);
|
||||
|
||||
if (flags & TCP_ACK) {
|
||||
right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2;
|
||||
@@ -809,9 +871,21 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
(pcb->snd_wl1 == seqno && TCP_SEQ_LT(pcb->snd_wl2, ackno)) ||
|
||||
(pcb->snd_wl2 == ackno && tcphdr->wnd > pcb->snd_wnd)) {
|
||||
pcb->snd_wnd = tcphdr->wnd;
|
||||
/* keep track of the biggest window announced by the remote host to calculate
|
||||
the maximum segment size */
|
||||
if (pcb->snd_wnd_max < tcphdr->wnd) {
|
||||
pcb->snd_wnd_max = tcphdr->wnd;
|
||||
}
|
||||
pcb->snd_wl1 = seqno;
|
||||
pcb->snd_wl2 = ackno;
|
||||
if (pcb->snd_wnd > 0 && pcb->persist_backoff > 0) {
|
||||
if (pcb->snd_wnd == 0) {
|
||||
if (pcb->persist_backoff == 0) {
|
||||
/* start persist timer */
|
||||
pcb->persist_cnt = 0;
|
||||
pcb->persist_backoff = 1;
|
||||
}
|
||||
} else if (pcb->persist_backoff > 0) {
|
||||
/* stop persist timer */
|
||||
pcb->persist_backoff = 0;
|
||||
}
|
||||
LWIP_DEBUGF(TCP_WND_DEBUG, ("tcp_receive: window update %"U16_F"\n", pcb->snd_wnd));
|
||||
@@ -858,8 +932,9 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
/* Clause 5 */
|
||||
if (pcb->lastack == ackno) {
|
||||
found_dupack = 1;
|
||||
if (pcb->dupacks + 1 > pcb->dupacks)
|
||||
if ((u8_t)(pcb->dupacks + 1) > pcb->dupacks) {
|
||||
++pcb->dupacks;
|
||||
}
|
||||
if (pcb->dupacks > 3) {
|
||||
/* Inflate the congestion window, but not if it means that
|
||||
the value overflows. */
|
||||
@@ -986,6 +1061,11 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
|
||||
next = pcb->unsent;
|
||||
pcb->unsent = pcb->unsent->next;
|
||||
#if TCP_OVERSIZE
|
||||
if (pcb->unsent == NULL) {
|
||||
pcb->unsent_oversize = 0;
|
||||
}
|
||||
#endif /* TCP_OVERSIZE */
|
||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_receive: queuelen %"U16_F" ... ", (u16_t)pcb->snd_queuelen));
|
||||
LWIP_ASSERT("pcb->snd_queuelen >= pbuf_clen(next->p)", (pcb->snd_queuelen >= pbuf_clen(next->p)));
|
||||
/* Prevent ACK for FIN to generate a sent event */
|
||||
@@ -1034,8 +1114,10 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
}
|
||||
|
||||
/* If the incoming segment contains data, we must process it
|
||||
further. */
|
||||
if (tcplen > 0) {
|
||||
further unless the pcb already received a FIN.
|
||||
(RFC 793, chapeter 3.9, "SEGMENT ARRIVES" in states CLOSE-WAIT, CLOSING,
|
||||
LAST-ACK and TIME-WAIT: "Ignore the segment text.") */
|
||||
if ((tcplen > 0) && (pcb->state < CLOSE_WAIT)) {
|
||||
/* This code basically does three things:
|
||||
|
||||
+) If the incoming segment contains data that is the next
|
||||
@@ -1113,9 +1195,6 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
LWIP_ASSERT("pbuf_header failed", 0);
|
||||
}
|
||||
}
|
||||
/* KJM following line changed to use p->payload rather than inseg->p->payload
|
||||
to fix bug #9076 */
|
||||
inseg.dataptr = p->payload;
|
||||
inseg.len -= (u16_t)(pcb->rcv_nxt - seqno);
|
||||
inseg.tcphdr->seqno = seqno = pcb->rcv_nxt;
|
||||
}
|
||||
@@ -1143,7 +1222,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
if (tcplen > pcb->rcv_wnd) {
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG,
|
||||
("tcp_receive: other end overran receive window"
|
||||
"seqno %"U32_F" len %"U32_F" right edge %"U32_F"\n",
|
||||
"seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n",
|
||||
seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
|
||||
if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
|
||||
/* Must remove the FIN from the header as we're trimming
|
||||
@@ -1161,60 +1240,52 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
(seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd));
|
||||
}
|
||||
#if TCP_QUEUE_OOSEQ
|
||||
/* Received in-sequence data, adjust ooseq data if:
|
||||
- FIN has been received or
|
||||
- inseq overlaps with ooseq */
|
||||
if (pcb->ooseq != NULL) {
|
||||
if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG,
|
||||
("tcp_receive: received in-order FIN, binning ooseq queue\n"));
|
||||
/* Received in-order FIN means anything that was received
|
||||
* out of order must now have been received in-order, so
|
||||
* bin the ooseq queue
|
||||
* rcv_nxt
|
||||
* . |--ooseq--|
|
||||
* .==seg============|FIN
|
||||
*/
|
||||
* bin the ooseq queue */
|
||||
while (pcb->ooseq != NULL) {
|
||||
struct tcp_seg *old_ooseq = pcb->ooseq;
|
||||
pcb->ooseq = pcb->ooseq->next;
|
||||
tcp_seg_free(old_ooseq);
|
||||
}
|
||||
}
|
||||
else {
|
||||
struct tcp_seg* next = pcb->ooseq;
|
||||
struct tcp_seg *old_seg;
|
||||
/* rcv_nxt
|
||||
* . |--ooseq--|
|
||||
* .==seg============|
|
||||
*/
|
||||
}
|
||||
} else {
|
||||
next = pcb->ooseq;
|
||||
/* Remove all segments on ooseq that are covered by inseg already.
|
||||
* FIN is copied from ooseq to inseg if present. */
|
||||
while (next &&
|
||||
TCP_SEQ_GEQ(seqno + tcplen,
|
||||
next->tcphdr->seqno + next->len)) {
|
||||
/* inseg doesn't have FIN (already processed) */
|
||||
/* inseg cannot have FIN here (already processed above) */
|
||||
if (TCPH_FLAGS(next->tcphdr) & TCP_FIN &&
|
||||
(TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) {
|
||||
TCPH_FLAGS_SET(inseg.tcphdr,
|
||||
TCPH_FLAGS(inseg.tcphdr) | TCP_FIN);
|
||||
TCPH_SET_FLAG(inseg.tcphdr, TCP_FIN);
|
||||
tcplen = TCP_TCPLEN(&inseg);
|
||||
}
|
||||
old_seg = next;
|
||||
prev = next;
|
||||
next = next->next;
|
||||
tcp_seg_free(old_seg);
|
||||
tcp_seg_free(prev);
|
||||
}
|
||||
/* rcv_nxt
|
||||
* . |--ooseq--|
|
||||
* .==seg============|
|
||||
*/
|
||||
/* Now trim right side of inseg if it overlaps with the first
|
||||
* segment on ooseq */
|
||||
if (next &&
|
||||
TCP_SEQ_GT(seqno + tcplen,
|
||||
next->tcphdr->seqno)) {
|
||||
/* FIN in inseg already handled by dropping whole ooseq queue */
|
||||
inseg.len = (u16_t)(pcb->ooseq->tcphdr->seqno - seqno);
|
||||
/* inseg cannot have FIN here (already processed above) */
|
||||
inseg.len = (u16_t)(next->tcphdr->seqno - seqno);
|
||||
if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
|
||||
inseg.len -= 1;
|
||||
}
|
||||
pbuf_realloc(inseg.p, inseg.len);
|
||||
tcplen = TCP_TCPLEN(&inseg);
|
||||
LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n",
|
||||
(seqno + tcplen) == pcb->ooseq->tcphdr->seqno);
|
||||
(seqno + tcplen) == next->tcphdr->seqno);
|
||||
}
|
||||
pcb->ooseq = next;
|
||||
}
|
||||
@@ -1252,7 +1323,7 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
|
||||
#if TCP_QUEUE_OOSEQ
|
||||
/* We now check if we have segments on the ->ooseq queue that
|
||||
is now in sequence. */
|
||||
are now in sequence. */
|
||||
while (pcb->ooseq != NULL &&
|
||||
pcb->ooseq->tcphdr->seqno == pcb->rcv_nxt) {
|
||||
|
||||
@@ -1392,6 +1463,24 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
next->len = (u16_t)(seqno - next->tcphdr->seqno);
|
||||
pbuf_realloc(next->p, next->len);
|
||||
}
|
||||
/* check if the remote side overruns our receive window */
|
||||
if ((u32_t)tcplen + seqno > pcb->rcv_nxt + (u32_t)pcb->rcv_wnd) {
|
||||
LWIP_DEBUGF(TCP_INPUT_DEBUG,
|
||||
("tcp_receive: other end overran receive window"
|
||||
"seqno %"U32_F" len %"U16_F" right edge %"U32_F"\n",
|
||||
seqno, tcplen, pcb->rcv_nxt + pcb->rcv_wnd));
|
||||
if (TCPH_FLAGS(next->next->tcphdr) & TCP_FIN) {
|
||||
/* Must remove the FIN from the header as we're trimming
|
||||
* that byte of sequence-space from the packet */
|
||||
TCPH_FLAGS_SET(next->next->tcphdr, TCPH_FLAGS(next->next->tcphdr) &~ TCP_FIN);
|
||||
}
|
||||
/* Adjust length of segment to fit in the window. */
|
||||
next->next->len = pcb->rcv_nxt + pcb->rcv_wnd - seqno;
|
||||
pbuf_realloc(next->next->p, next->next->len);
|
||||
tcplen = TCP_TCPLEN(next->next);
|
||||
LWIP_ASSERT("tcp_receive: segment not trimmed correctly to rcv_wnd\n",
|
||||
(seqno + tcplen) == (pcb->rcv_nxt + pcb->rcv_wnd));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1399,8 +1488,32 @@ tcp_receive(struct tcp_pcb *pcb)
|
||||
prev = next;
|
||||
}
|
||||
}
|
||||
#if TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS
|
||||
/* Check that the data on ooseq doesn't exceed one of the limits
|
||||
and throw away everything above that limit. */
|
||||
ooseq_blen = 0;
|
||||
ooseq_qlen = 0;
|
||||
prev = NULL;
|
||||
for(next = pcb->ooseq; next != NULL; prev = next, next = next->next) {
|
||||
struct pbuf *p = next->p;
|
||||
ooseq_blen += p->tot_len;
|
||||
ooseq_qlen += pbuf_clen(p);
|
||||
if ((ooseq_blen > TCP_OOSEQ_MAX_BYTES) ||
|
||||
(ooseq_qlen > TCP_OOSEQ_MAX_PBUFS)) {
|
||||
/* too much ooseq data, dump this and everything after it */
|
||||
tcp_segs_free(next);
|
||||
if (prev == NULL) {
|
||||
/* first ooseq segment is too much, dump the whole queue */
|
||||
pcb->ooseq = NULL;
|
||||
} else {
|
||||
/* just dump 'next' and everything after it */
|
||||
prev->next = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* TCP_OOSEQ_MAX_BYTES || TCP_OOSEQ_MAX_PBUFS */
|
||||
#endif /* TCP_QUEUE_OOSEQ */
|
||||
|
||||
}
|
||||
} else {
|
||||
/* The incoming segment is not withing the window. */
|
||||
|
||||
1129
src/core/tcp_out.c
1129
src/core/tcp_out.c
File diff suppressed because it is too large
Load Diff
487
src/core/timers.c
Normal file
487
src/core/timers.c
Normal file
@@ -0,0 +1,487 @@
|
||||
/**
|
||||
* @file
|
||||
* Stack-internal timers implementation.
|
||||
* This file includes timer callbacks for stack-internal timers as well as
|
||||
* functions to set up or stop timers and check for expired timers.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
* Simon Goldschmidt
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/timers.h"
|
||||
#include "lwip/tcp_impl.h"
|
||||
|
||||
#if LWIP_TIMERS
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/tcpip.h"
|
||||
|
||||
#include "lwip/ip_frag.h"
|
||||
#include "netif/etharp.h"
|
||||
#include "lwip/dhcp.h"
|
||||
#include "lwip/autoip.h"
|
||||
#include "lwip/igmp.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/pbuf.h"
|
||||
|
||||
|
||||
/** The one and only timeout list */
|
||||
static struct sys_timeo *next_timeout;
|
||||
#if NO_SYS
|
||||
static u32_t timeouts_last_time;
|
||||
#endif /* NO_SYS */
|
||||
|
||||
#if LWIP_TCP
|
||||
/** global variable that shows if the tcp timer is currently scheduled or not */
|
||||
static int tcpip_tcp_timer_active;
|
||||
|
||||
/**
|
||||
* Timer callback function that calls tcp_tmr() and reschedules itself.
|
||||
*
|
||||
* @param arg unused argument
|
||||
*/
|
||||
static void
|
||||
tcpip_tcp_timer(void *arg)
|
||||
{
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
|
||||
/* call TCP timer handler */
|
||||
tcp_tmr();
|
||||
/* timer still needed? */
|
||||
if (tcp_active_pcbs || tcp_tw_pcbs) {
|
||||
/* restart timer */
|
||||
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
|
||||
} else {
|
||||
/* disable timer */
|
||||
tcpip_tcp_timer_active = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from TCP_REG when registering a new PCB:
|
||||
* the reason is to have the TCP timer only running when
|
||||
* there are active (or time-wait) PCBs.
|
||||
*/
|
||||
void
|
||||
tcp_timer_needed(void)
|
||||
{
|
||||
/* timer is off but needed again? */
|
||||
if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
|
||||
/* enable and start timer */
|
||||
tcpip_tcp_timer_active = 1;
|
||||
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_TCP */
|
||||
|
||||
#if IP_REASSEMBLY
|
||||
/**
|
||||
* Timer callback function that calls ip_reass_tmr() and reschedules itself.
|
||||
*
|
||||
* @param arg unused argument
|
||||
*/
|
||||
static void
|
||||
ip_reass_timer(void *arg)
|
||||
{
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: ip_reass_tmr()\n"));
|
||||
ip_reass_tmr();
|
||||
sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL);
|
||||
}
|
||||
#endif /* IP_REASSEMBLY */
|
||||
|
||||
#if LWIP_ARP
|
||||
/**
|
||||
* Timer callback function that calls etharp_tmr() and reschedules itself.
|
||||
*
|
||||
* @param arg unused argument
|
||||
*/
|
||||
static void
|
||||
arp_timer(void *arg)
|
||||
{
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: etharp_tmr()\n"));
|
||||
etharp_tmr();
|
||||
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
|
||||
}
|
||||
#endif /* LWIP_ARP */
|
||||
|
||||
#if LWIP_DHCP
|
||||
/**
|
||||
* Timer callback function that calls dhcp_coarse_tmr() and reschedules itself.
|
||||
*
|
||||
* @param arg unused argument
|
||||
*/
|
||||
static void
|
||||
dhcp_timer_coarse(void *arg)
|
||||
{
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_coarse_tmr()\n"));
|
||||
dhcp_coarse_tmr();
|
||||
sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Timer callback function that calls dhcp_fine_tmr() and reschedules itself.
|
||||
*
|
||||
* @param arg unused argument
|
||||
*/
|
||||
static void
|
||||
dhcp_timer_fine(void *arg)
|
||||
{
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_fine_tmr()\n"));
|
||||
dhcp_fine_tmr();
|
||||
sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
|
||||
}
|
||||
#endif /* LWIP_DHCP */
|
||||
|
||||
#if LWIP_AUTOIP
|
||||
/**
|
||||
* Timer callback function that calls autoip_tmr() and reschedules itself.
|
||||
*
|
||||
* @param arg unused argument
|
||||
*/
|
||||
static void
|
||||
autoip_timer(void *arg)
|
||||
{
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: autoip_tmr()\n"));
|
||||
autoip_tmr();
|
||||
sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL);
|
||||
}
|
||||
#endif /* LWIP_AUTOIP */
|
||||
|
||||
#if LWIP_IGMP
|
||||
/**
|
||||
* Timer callback function that calls igmp_tmr() and reschedules itself.
|
||||
*
|
||||
* @param arg unused argument
|
||||
*/
|
||||
static void
|
||||
igmp_timer(void *arg)
|
||||
{
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: igmp_tmr()\n"));
|
||||
igmp_tmr();
|
||||
sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL);
|
||||
}
|
||||
#endif /* LWIP_IGMP */
|
||||
|
||||
#if LWIP_DNS
|
||||
/**
|
||||
* Timer callback function that calls dns_tmr() and reschedules itself.
|
||||
*
|
||||
* @param arg unused argument
|
||||
*/
|
||||
static void
|
||||
dns_timer(void *arg)
|
||||
{
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dns_tmr()\n"));
|
||||
dns_tmr();
|
||||
sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL);
|
||||
}
|
||||
#endif /* LWIP_DNS */
|
||||
|
||||
/** Initialize this module */
|
||||
void sys_timeouts_init(void)
|
||||
{
|
||||
#if IP_REASSEMBLY
|
||||
sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL);
|
||||
#endif /* IP_REASSEMBLY */
|
||||
#if LWIP_ARP
|
||||
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
|
||||
#endif /* LWIP_ARP */
|
||||
#if LWIP_DHCP
|
||||
sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL);
|
||||
sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
|
||||
#endif /* LWIP_DHCP */
|
||||
#if LWIP_AUTOIP
|
||||
sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL);
|
||||
#endif /* LWIP_AUTOIP */
|
||||
#if LWIP_IGMP
|
||||
sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL);
|
||||
#endif /* LWIP_IGMP */
|
||||
#if LWIP_DNS
|
||||
sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL);
|
||||
#endif /* LWIP_DNS */
|
||||
|
||||
#if NO_SYS
|
||||
/* Initialise timestamp for sys_check_timeouts */
|
||||
timeouts_last_time = sys_now();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a one-shot timer (aka timeout). Timeouts are processed in the
|
||||
* following cases:
|
||||
* - while waiting for a message using sys_timeouts_mbox_fetch()
|
||||
* - by calling sys_check_timeouts() (NO_SYS==1 only)
|
||||
*
|
||||
* @param msecs time in milliseconds after that the timer should expire
|
||||
* @param handler callback function to call when msecs have elapsed
|
||||
* @param arg argument to pass to the callback function
|
||||
*/
|
||||
#if LWIP_DEBUG_TIMERNAMES
|
||||
void
|
||||
sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name)
|
||||
#else /* LWIP_DEBUG_TIMERNAMES */
|
||||
void
|
||||
sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg)
|
||||
#endif /* LWIP_DEBUG_TIMERNAMES */
|
||||
{
|
||||
struct sys_timeo *timeout, *t;
|
||||
|
||||
timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT);
|
||||
if (timeout == NULL) {
|
||||
LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL);
|
||||
return;
|
||||
}
|
||||
timeout->next = NULL;
|
||||
timeout->h = handler;
|
||||
timeout->arg = arg;
|
||||
timeout->time = msecs;
|
||||
#if LWIP_DEBUG_TIMERNAMES
|
||||
timeout->handler_name = handler_name;
|
||||
LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" handler=%s arg=%p\n",
|
||||
(void *)timeout, msecs, handler_name, (void *)arg));
|
||||
#endif /* LWIP_DEBUG_TIMERNAMES */
|
||||
|
||||
if (next_timeout == NULL) {
|
||||
next_timeout = timeout;
|
||||
return;
|
||||
}
|
||||
|
||||
if (next_timeout->time > msecs) {
|
||||
next_timeout->time -= msecs;
|
||||
timeout->next = next_timeout;
|
||||
next_timeout = timeout;
|
||||
} else {
|
||||
for(t = next_timeout; t != NULL; t = t->next) {
|
||||
timeout->time -= t->time;
|
||||
if (t->next == NULL || t->next->time > timeout->time) {
|
||||
if (t->next != NULL) {
|
||||
t->next->time -= timeout->time;
|
||||
}
|
||||
timeout->next = t->next;
|
||||
t->next = timeout;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Go through timeout list (for this task only) and remove the first matching
|
||||
* entry, even though the timeout has not triggered yet.
|
||||
*
|
||||
* @note This function only works as expected if there is only one timeout
|
||||
* calling 'handler' in the list of timeouts.
|
||||
*
|
||||
* @param handler callback function that would be called by the timeout
|
||||
* @param arg callback argument that would be passed to handler
|
||||
*/
|
||||
void
|
||||
sys_untimeout(sys_timeout_handler handler, void *arg)
|
||||
{
|
||||
struct sys_timeo *prev_t, *t;
|
||||
|
||||
if (next_timeout == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (t = next_timeout, prev_t = NULL; t != NULL; prev_t = t, t = t->next) {
|
||||
if ((t->h == handler) && (t->arg == arg)) {
|
||||
/* We have a match */
|
||||
/* Unlink from previous in list */
|
||||
if (prev_t == NULL) {
|
||||
next_timeout = t->next;
|
||||
} else {
|
||||
prev_t->next = t->next;
|
||||
}
|
||||
/* If not the last one, add time of this one back to next */
|
||||
if (t->next != NULL) {
|
||||
t->next->time += t->time;
|
||||
}
|
||||
memp_free(MEMP_SYS_TIMEOUT, t);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#if NO_SYS
|
||||
|
||||
/** Handle timeouts for NO_SYS==1 (i.e. without using
|
||||
* tcpip_thread/sys_timeouts_mbox_fetch(). Uses sys_now() to call timeout
|
||||
* handler functions when timeouts expire.
|
||||
*
|
||||
* Must be called periodically from your main loop.
|
||||
*/
|
||||
void
|
||||
sys_check_timeouts(void)
|
||||
{
|
||||
if (next_timeout) {
|
||||
struct sys_timeo *tmptimeout;
|
||||
u32_t diff;
|
||||
sys_timeout_handler handler;
|
||||
void *arg;
|
||||
u8_t had_one;
|
||||
u32_t now;
|
||||
|
||||
now = sys_now();
|
||||
/* this cares for wraparounds */
|
||||
diff = now - timeouts_last_time;
|
||||
do
|
||||
{
|
||||
#if PBUF_POOL_FREE_OOSEQ
|
||||
PBUF_CHECK_FREE_OOSEQ();
|
||||
#endif /* PBUF_POOL_FREE_OOSEQ */
|
||||
had_one = 0;
|
||||
tmptimeout = next_timeout;
|
||||
if (tmptimeout && (tmptimeout->time <= diff)) {
|
||||
/* timeout has expired */
|
||||
had_one = 1;
|
||||
timeouts_last_time = now;
|
||||
diff -= tmptimeout->time;
|
||||
next_timeout = tmptimeout->next;
|
||||
handler = tmptimeout->h;
|
||||
arg = tmptimeout->arg;
|
||||
#if LWIP_DEBUG_TIMERNAMES
|
||||
if (handler != NULL) {
|
||||
LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s arg=%p\n",
|
||||
tmptimeout->handler_name, arg));
|
||||
}
|
||||
#endif /* LWIP_DEBUG_TIMERNAMES */
|
||||
memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
|
||||
if (handler != NULL) {
|
||||
handler(arg);
|
||||
}
|
||||
}
|
||||
/* repeat until all expired timers have been called */
|
||||
}while(had_one);
|
||||
}
|
||||
}
|
||||
|
||||
/** Set back the timestamp of the last call to sys_check_timeouts()
|
||||
* This is necessary if sys_check_timeouts() hasn't been called for a long
|
||||
* time (e.g. while saving energy) to prevent all timer functions of that
|
||||
* period being called.
|
||||
*/
|
||||
void
|
||||
sys_restart_timeouts(void)
|
||||
{
|
||||
timeouts_last_time = sys_now();
|
||||
}
|
||||
|
||||
#else /* NO_SYS */
|
||||
|
||||
/**
|
||||
* Wait (forever) for a message to arrive in an mbox.
|
||||
* While waiting, timeouts are processed.
|
||||
*
|
||||
* @param mbox the mbox to fetch the message from
|
||||
* @param msg the place to store the message
|
||||
*/
|
||||
void
|
||||
sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg)
|
||||
{
|
||||
u32_t time_needed;
|
||||
struct sys_timeo *tmptimeout;
|
||||
sys_timeout_handler handler;
|
||||
void *arg;
|
||||
|
||||
again:
|
||||
if (!next_timeout) {
|
||||
time_needed = sys_arch_mbox_fetch(mbox, msg, 0);
|
||||
} else {
|
||||
if (next_timeout->time > 0) {
|
||||
time_needed = sys_arch_mbox_fetch(mbox, msg, next_timeout->time);
|
||||
} else {
|
||||
time_needed = SYS_ARCH_TIMEOUT;
|
||||
}
|
||||
|
||||
if (time_needed == SYS_ARCH_TIMEOUT) {
|
||||
/* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
|
||||
could be fetched. We should now call the timeout handler and
|
||||
deallocate the memory allocated for the timeout. */
|
||||
tmptimeout = next_timeout;
|
||||
next_timeout = tmptimeout->next;
|
||||
handler = tmptimeout->h;
|
||||
arg = tmptimeout->arg;
|
||||
#if LWIP_DEBUG_TIMERNAMES
|
||||
if (handler != NULL) {
|
||||
LWIP_DEBUGF(TIMERS_DEBUG, ("stmf calling h=%s arg=%p\n",
|
||||
tmptimeout->handler_name, arg));
|
||||
}
|
||||
#endif /* LWIP_DEBUG_TIMERNAMES */
|
||||
memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
|
||||
if (handler != NULL) {
|
||||
/* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the
|
||||
timeout handler function. */
|
||||
LOCK_TCPIP_CORE();
|
||||
handler(arg);
|
||||
UNLOCK_TCPIP_CORE();
|
||||
}
|
||||
LWIP_TCPIP_THREAD_ALIVE();
|
||||
|
||||
/* We try again to fetch a message from the mbox. */
|
||||
goto again;
|
||||
} else {
|
||||
/* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
|
||||
occured. The time variable is set to the number of
|
||||
milliseconds we waited for the message. */
|
||||
if (time_needed < next_timeout->time) {
|
||||
next_timeout->time -= time_needed;
|
||||
} else {
|
||||
next_timeout->time = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* NO_SYS */
|
||||
|
||||
#else /* LWIP_TIMERS */
|
||||
/* Satisfy the TCP code which calls this function */
|
||||
void
|
||||
tcp_timer_needed(void)
|
||||
{
|
||||
}
|
||||
#endif /* LWIP_TIMERS */
|
||||
376
src/core/udp.c
376
src/core/udp.c
@@ -53,7 +53,6 @@
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
@@ -65,10 +64,77 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifndef UDP_LOCAL_PORT_RANGE_START
|
||||
/* From http://www.iana.org/assignments/port-numbers:
|
||||
"The Dynamic and/or Private Ports are those from 49152 through 65535" */
|
||||
#define UDP_LOCAL_PORT_RANGE_START 0xc000
|
||||
#define UDP_LOCAL_PORT_RANGE_END 0xffff
|
||||
#define UDP_ENSURE_LOCAL_PORT_RANGE(port) (((port) & ~UDP_LOCAL_PORT_RANGE_START) + UDP_LOCAL_PORT_RANGE_START)
|
||||
#endif
|
||||
|
||||
/* last local UDP port */
|
||||
static u16_t udp_port = UDP_LOCAL_PORT_RANGE_START;
|
||||
|
||||
/* The list of UDP PCBs */
|
||||
/* exported in udp.h (was static) */
|
||||
struct udp_pcb *udp_pcbs;
|
||||
|
||||
/**
|
||||
* Initialize this module.
|
||||
*/
|
||||
void
|
||||
udp_init(void)
|
||||
{
|
||||
#if LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND)
|
||||
udp_port = UDP_ENSURE_LOCAL_PORT_RANGE(LWIP_RAND());
|
||||
#endif /* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS && defined(LWIP_RAND) */
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a new local UDP port.
|
||||
*
|
||||
* @return a new (free) local UDP port number
|
||||
*/
|
||||
static u16_t
|
||||
udp_new_port(void)
|
||||
{
|
||||
u16_t n = 0;
|
||||
struct udp_pcb *pcb;
|
||||
|
||||
again:
|
||||
if (udp_port++ == UDP_LOCAL_PORT_RANGE_END) {
|
||||
udp_port = UDP_LOCAL_PORT_RANGE_START;
|
||||
}
|
||||
/* Check all PCBs. */
|
||||
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||
if (pcb->local_port == udp_port) {
|
||||
if (++n > (UDP_LOCAL_PORT_RANGE_END - UDP_LOCAL_PORT_RANGE_START)) {
|
||||
return 0;
|
||||
}
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
return udp_port;
|
||||
#if 0
|
||||
struct udp_pcb *ipcb = udp_pcbs;
|
||||
while ((ipcb != NULL) && (udp_port != UDP_LOCAL_PORT_RANGE_END)) {
|
||||
if (ipcb->local_port == udp_port) {
|
||||
/* port is already used by another udp_pcb */
|
||||
udp_port++;
|
||||
/* restart scanning all udp pcbs */
|
||||
ipcb = udp_pcbs;
|
||||
} else {
|
||||
/* go on with next udp pcb */
|
||||
ipcb = ipcb->next;
|
||||
}
|
||||
}
|
||||
if (ipcb != NULL) {
|
||||
return 0;
|
||||
}
|
||||
return udp_port;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an incoming UDP datagram.
|
||||
*
|
||||
@@ -96,7 +162,7 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
|
||||
UDP_STATS_INC(udp.recv);
|
||||
|
||||
iphdr = p->payload;
|
||||
iphdr = (struct ip_hdr *)p->payload;
|
||||
|
||||
/* Check minimum length (IP header + UDP header)
|
||||
* and move payload pointer to UDP header */
|
||||
@@ -114,7 +180,7 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
udphdr = (struct udp_hdr *)p->payload;
|
||||
|
||||
/* is broadcast packet ? */
|
||||
broadcast = ip_addr_isbroadcast(&(iphdr->dest), inp);
|
||||
broadcast = ip_addr_isbroadcast(¤t_iphdr_dest, inp);
|
||||
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len));
|
||||
|
||||
@@ -128,10 +194,10 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
LWIP_DEBUGF(UDP_DEBUG,
|
||||
("udp (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") <-- "
|
||||
"(%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n",
|
||||
ip4_addr1(&iphdr->dest), ip4_addr2(&iphdr->dest),
|
||||
ip4_addr3(&iphdr->dest), ip4_addr4(&iphdr->dest), ntohs(udphdr->dest),
|
||||
ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src),
|
||||
ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src), ntohs(udphdr->src)));
|
||||
ip4_addr1_16(&iphdr->dest), ip4_addr2_16(&iphdr->dest),
|
||||
ip4_addr3_16(&iphdr->dest), ip4_addr4_16(&iphdr->dest), ntohs(udphdr->dest),
|
||||
ip4_addr1_16(&iphdr->src), ip4_addr2_16(&iphdr->src),
|
||||
ip4_addr3_16(&iphdr->src), ip4_addr4_16(&iphdr->src), ntohs(udphdr->src)));
|
||||
|
||||
#if LWIP_DHCP
|
||||
pcb = NULL;
|
||||
@@ -145,7 +211,7 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
(- broadcast or directed to us) -> DHCP is link-layer-addressed, local ip is always ANY!
|
||||
- inp->dhcp->pcb->remote == ANY or iphdr->src */
|
||||
if ((ip_addr_isany(&inp->dhcp->pcb->remote_ip) ||
|
||||
ip_addr_cmp(&(inp->dhcp->pcb->remote_ip), &(iphdr->src)))) {
|
||||
ip_addr_cmp(&(inp->dhcp->pcb->remote_ip), ¤t_iphdr_src))) {
|
||||
pcb = inp->dhcp->pcb;
|
||||
}
|
||||
}
|
||||
@@ -166,35 +232,41 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
LWIP_DEBUGF(UDP_DEBUG,
|
||||
("pcb (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") --- "
|
||||
"(%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n",
|
||||
ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
|
||||
ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,
|
||||
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
|
||||
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip), pcb->remote_port));
|
||||
ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip),
|
||||
ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip), pcb->local_port,
|
||||
ip4_addr1_16(&pcb->remote_ip), ip4_addr2_16(&pcb->remote_ip),
|
||||
ip4_addr3_16(&pcb->remote_ip), ip4_addr4_16(&pcb->remote_ip), pcb->remote_port));
|
||||
|
||||
/* compare PCB local addr+port to UDP destination addr+port */
|
||||
if ((pcb->local_port == dest) &&
|
||||
((!broadcast && ip_addr_isany(&pcb->local_ip)) ||
|
||||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)) ||
|
||||
if (pcb->local_port == dest) {
|
||||
if (
|
||||
(!broadcast && ip_addr_isany(&pcb->local_ip)) ||
|
||||
ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest) ||
|
||||
#if LWIP_IGMP
|
||||
ip_addr_ismulticast(&(iphdr->dest)) ||
|
||||
ip_addr_ismulticast(¤t_iphdr_dest) ||
|
||||
#endif /* LWIP_IGMP */
|
||||
#if IP_SOF_BROADCAST_RECV
|
||||
(broadcast && (pcb->so_options & SOF_BROADCAST)))) {
|
||||
#else /* IP_SOF_BROADCAST_RECV */
|
||||
(broadcast))) {
|
||||
#endif /* IP_SOF_BROADCAST_RECV */
|
||||
local_match = 1;
|
||||
if ((uncon_pcb == NULL) &&
|
||||
((pcb->flags & UDP_FLAGS_CONNECTED) == 0)) {
|
||||
/* the first unconnected matching PCB */
|
||||
uncon_pcb = pcb;
|
||||
(broadcast && ip_get_option(pcb, SOF_BROADCAST) &&
|
||||
(ip_addr_isany(&pcb->local_ip) ||
|
||||
ip_addr_netcmp(&pcb->local_ip, ip_current_dest_addr(), &inp->netmask)))) {
|
||||
#else /* IP_SOF_BROADCAST_RECV */
|
||||
(broadcast &&
|
||||
(ip_addr_isany(&pcb->local_ip) ||
|
||||
ip_addr_netcmp(&pcb->local_ip, ip_current_dest_addr(), &inp->netmask)))) {
|
||||
#endif /* IP_SOF_BROADCAST_RECV */
|
||||
local_match = 1;
|
||||
if ((uncon_pcb == NULL) &&
|
||||
((pcb->flags & UDP_FLAGS_CONNECTED) == 0)) {
|
||||
/* the first unconnected matching PCB */
|
||||
uncon_pcb = pcb;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* compare PCB remote addr+port to UDP source addr+port */
|
||||
if ((local_match != 0) &&
|
||||
(pcb->remote_port == src) &&
|
||||
(ip_addr_isany(&pcb->remote_ip) ||
|
||||
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)))) {
|
||||
ip_addr_cmp(&(pcb->remote_ip), ¤t_iphdr_src))) {
|
||||
/* the first fully matching PCB */
|
||||
if (prev != NULL) {
|
||||
/* move the pcb to the front of udp_pcbs so that is
|
||||
@@ -216,7 +288,7 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
}
|
||||
|
||||
/* Check checksum if this is a match or if it was directed at us. */
|
||||
if (pcb != NULL || ip_addr_cmp(&inp->ip_addr, &iphdr->dest)) {
|
||||
if (pcb != NULL || ip_addr_cmp(&inp->ip_addr, ¤t_iphdr_dest)) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: calculating checksum\n"));
|
||||
#if LWIP_UDPLITE
|
||||
if (IPH_PROTO(iphdr) == IP_PROTO_UDPLITE) {
|
||||
@@ -238,8 +310,7 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
if (inet_chksum_pseudo_partial(p, (struct ip_addr *)&(iphdr->src),
|
||||
(struct ip_addr *)&(iphdr->dest),
|
||||
if (inet_chksum_pseudo_partial(p, ¤t_iphdr_src, ¤t_iphdr_dest,
|
||||
IP_PROTO_UDPLITE, p->tot_len, chklen) != 0) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
|
||||
@@ -255,8 +326,7 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
#if CHECKSUM_CHECK_UDP
|
||||
if (udphdr->chksum != 0) {
|
||||
if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
|
||||
(struct ip_addr *)&(iphdr->dest),
|
||||
if (inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(),
|
||||
IP_PROTO_UDP, p->tot_len) != 0) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("udp_input: UDP datagram discarded due to failing checksum\n"));
|
||||
@@ -279,10 +349,58 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
}
|
||||
if (pcb != NULL) {
|
||||
snmp_inc_udpindatagrams();
|
||||
#if SO_REUSE && SO_REUSE_RXTOALL
|
||||
if ((broadcast || ip_addr_ismulticast(¤t_iphdr_dest)) &&
|
||||
ip_get_option(pcb, SOF_REUSEADDR)) {
|
||||
/* pass broadcast- or multicast packets to all multicast pcbs
|
||||
if SOF_REUSEADDR is set on the first match */
|
||||
struct udp_pcb *mpcb;
|
||||
u8_t p_header_changed = 0;
|
||||
for (mpcb = udp_pcbs; mpcb != NULL; mpcb = mpcb->next) {
|
||||
if (mpcb != pcb) {
|
||||
/* compare PCB local addr+port to UDP destination addr+port */
|
||||
if ((mpcb->local_port == dest) &&
|
||||
((!broadcast && ip_addr_isany(&mpcb->local_ip)) ||
|
||||
ip_addr_cmp(&(mpcb->local_ip), ¤t_iphdr_dest) ||
|
||||
#if LWIP_IGMP
|
||||
ip_addr_ismulticast(¤t_iphdr_dest) ||
|
||||
#endif /* LWIP_IGMP */
|
||||
#if IP_SOF_BROADCAST_RECV
|
||||
(broadcast && ip_get_option(mpcb, SOF_BROADCAST)))) {
|
||||
#else /* IP_SOF_BROADCAST_RECV */
|
||||
(broadcast))) {
|
||||
#endif /* IP_SOF_BROADCAST_RECV */
|
||||
/* pass a copy of the packet to all local matches */
|
||||
if (mpcb->recv != NULL) {
|
||||
struct pbuf *q;
|
||||
/* for that, move payload to IP header again */
|
||||
if (p_header_changed == 0) {
|
||||
pbuf_header(p, (s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
|
||||
p_header_changed = 1;
|
||||
}
|
||||
q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
|
||||
if (q != NULL) {
|
||||
err_t err = pbuf_copy(q, p);
|
||||
if (err == ERR_OK) {
|
||||
/* move payload to UDP data */
|
||||
pbuf_header(q, -(s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
|
||||
mpcb->recv(mpcb->recv_arg, mpcb, q, ip_current_src_addr(), src);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (p_header_changed) {
|
||||
/* and move payload to UDP data again */
|
||||
pbuf_header(p, -(s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
|
||||
}
|
||||
}
|
||||
#endif /* SO_REUSE && SO_REUSE_RXTOALL */
|
||||
/* callback */
|
||||
if (pcb->recv != NULL) {
|
||||
/* now the recv function is responsible for freeing p */
|
||||
pcb->recv(pcb->recv_arg, pcb, p, &iphdr->src, src);
|
||||
pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr(), src);
|
||||
} else {
|
||||
/* no recv function registered? then we have to free the pbuf! */
|
||||
pbuf_free(p);
|
||||
@@ -295,7 +413,7 @@ udp_input(struct pbuf *p, struct netif *inp)
|
||||
/* No match was found, send ICMP destination port unreachable unless
|
||||
destination address was broadcast/multicast. */
|
||||
if (!broadcast &&
|
||||
!ip_addr_ismulticast(&iphdr->dest)) {
|
||||
!ip_addr_ismulticast(¤t_iphdr_dest)) {
|
||||
/* move payload pointer back to ip header */
|
||||
pbuf_header(p, (IPH_HL(iphdr) * 4) + UDP_HLEN);
|
||||
LWIP_ASSERT("p->payload == iphdr", (p->payload == iphdr));
|
||||
@@ -339,6 +457,19 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
||||
return udp_sendto(pcb, p, &pcb->remote_ip, pcb->remote_port);
|
||||
}
|
||||
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
/** Same as udp_send() but with checksum
|
||||
*/
|
||||
err_t
|
||||
udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p,
|
||||
u8_t have_chksum, u16_t chksum)
|
||||
{
|
||||
/* send to the packet using remote ip and port stored in the pcb */
|
||||
return udp_sendto_chksum(pcb, p, &pcb->remote_ip, pcb->remote_port,
|
||||
have_chksum, chksum);
|
||||
}
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
|
||||
/**
|
||||
* Send data to a specified address using UDP.
|
||||
*
|
||||
@@ -358,8 +489,18 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
||||
*/
|
||||
err_t
|
||||
udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
|
||||
struct ip_addr *dst_ip, u16_t dst_port)
|
||||
ip_addr_t *dst_ip, u16_t dst_port)
|
||||
{
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
return udp_sendto_chksum(pcb, p, dst_ip, dst_port, 0, 0);
|
||||
}
|
||||
|
||||
/** Same as udp_sendto(), but with checksum */
|
||||
err_t
|
||||
udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
u16_t dst_port, u8_t have_chksum, u16_t chksum)
|
||||
{
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
struct netif *netif;
|
||||
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_send\n"));
|
||||
@@ -373,11 +514,16 @@ udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
|
||||
|
||||
/* no outgoing network interface could be found? */
|
||||
if (netif == NULL) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to 0x%"X32_F"\n", dst_ip->addr));
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
ip4_addr1_16(dst_ip), ip4_addr2_16(dst_ip), ip4_addr3_16(dst_ip), ip4_addr4_16(dst_ip)));
|
||||
UDP_STATS_INC(udp.rterr);
|
||||
return ERR_RTE;
|
||||
}
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum);
|
||||
#else /* LWIP_CHECKSUM_ON_COPY */
|
||||
return udp_sendto_if(pcb, p, dst_ip, dst_port, netif);
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -401,16 +547,27 @@ udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
|
||||
*/
|
||||
err_t
|
||||
udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
|
||||
struct ip_addr *dst_ip, u16_t dst_port, struct netif *netif)
|
||||
ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif)
|
||||
{
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
return udp_sendto_if_chksum(pcb, p, dst_ip, dst_port, netif, 0, 0);
|
||||
}
|
||||
|
||||
/** Same as udp_sendto_if(), but with checksum */
|
||||
err_t
|
||||
udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip,
|
||||
u16_t dst_port, struct netif *netif, u8_t have_chksum,
|
||||
u16_t chksum)
|
||||
{
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
struct udp_hdr *udphdr;
|
||||
struct ip_addr *src_ip;
|
||||
ip_addr_t *src_ip;
|
||||
err_t err;
|
||||
struct pbuf *q; /* q will be sent down the stack */
|
||||
|
||||
#if IP_SOF_BROADCAST
|
||||
/* broadcast filter? */
|
||||
if ( ((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(dst_ip, netif) ) {
|
||||
if (!ip_get_option(pcb, SOF_BROADCAST) && ip_addr_isbroadcast(dst_ip, netif)) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
|
||||
("udp_sendto_if: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
|
||||
return ERR_VAL;
|
||||
@@ -436,8 +593,10 @@ udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: could not allocate header\n"));
|
||||
return ERR_MEM;
|
||||
}
|
||||
/* chain header q in front of given pbuf p */
|
||||
pbuf_chain(q, p);
|
||||
if (p->tot_len != 0) {
|
||||
/* chain header q in front of given pbuf p (only if p contains data) */
|
||||
pbuf_chain(q, p);
|
||||
}
|
||||
/* first pbuf q points to header pbuf */
|
||||
LWIP_DEBUGF(UDP_DEBUG,
|
||||
("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
|
||||
@@ -450,12 +609,20 @@ udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
|
||||
LWIP_ASSERT("check that first pbuf can hold struct udp_hdr",
|
||||
(q->len >= sizeof(struct udp_hdr)));
|
||||
/* q now represents the packet to be sent */
|
||||
udphdr = q->payload;
|
||||
udphdr = (struct udp_hdr *)q->payload;
|
||||
udphdr->src = htons(pcb->local_port);
|
||||
udphdr->dest = htons(dst_port);
|
||||
/* in UDP, 0 checksum means 'no checksum' */
|
||||
udphdr->chksum = 0x0000;
|
||||
|
||||
/* Multicast Loop? */
|
||||
#if LWIP_IGMP
|
||||
if (ip_addr_ismulticast(dst_ip) && ((pcb->flags & UDP_FLAGS_MULTICAST_LOOP) != 0)) {
|
||||
q->flags |= PBUF_FLAG_MCASTLOOP;
|
||||
}
|
||||
#endif /* LWIP_IGMP */
|
||||
|
||||
|
||||
/* PCB local address is IP_ANY_ADDR? */
|
||||
if (ip_addr_isany(&pcb->local_ip)) {
|
||||
/* use outgoing network interface IP address as source address */
|
||||
@@ -503,20 +670,28 @@ udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
|
||||
/* calculate checksum */
|
||||
#if CHECKSUM_GEN_UDP
|
||||
udphdr->chksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip,
|
||||
IP_PROTO_UDPLITE, q->tot_len, chklen);
|
||||
IP_PROTO_UDPLITE, q->tot_len,
|
||||
#if !LWIP_CHECKSUM_ON_COPY
|
||||
chklen);
|
||||
#else /* !LWIP_CHECKSUM_ON_COPY */
|
||||
(have_chksum ? UDP_HLEN : chklen));
|
||||
if (have_chksum) {
|
||||
u32_t acc;
|
||||
acc = udphdr->chksum + (u16_t)~(chksum);
|
||||
udphdr->chksum = FOLD_U32T(acc);
|
||||
}
|
||||
#endif /* !LWIP_CHECKSUM_ON_COPY */
|
||||
|
||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||
if (udphdr->chksum == 0x0000)
|
||||
if (udphdr->chksum == 0x0000) {
|
||||
udphdr->chksum = 0xffff;
|
||||
#endif /* CHECKSUM_CHECK_UDP */
|
||||
}
|
||||
#endif /* CHECKSUM_GEN_UDP */
|
||||
/* output to IP */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDPLITE,)\n"));
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
netif->addr_hint = &(pcb->addr_hint);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint);
|
||||
err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
netif->addr_hint = NULL;
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
NETIF_SET_HWADDRHINT(netif, NULL);
|
||||
} else
|
||||
#endif /* LWIP_UDPLITE */
|
||||
{ /* UDP */
|
||||
@@ -525,21 +700,33 @@ udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
|
||||
/* calculate checksum */
|
||||
#if CHECKSUM_GEN_UDP
|
||||
if ((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
|
||||
udphdr->chksum = inet_chksum_pseudo(q, src_ip, dst_ip, IP_PROTO_UDP, q->tot_len);
|
||||
u16_t udpchksum;
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
if (have_chksum) {
|
||||
u32_t acc;
|
||||
udpchksum = inet_chksum_pseudo_partial(q, src_ip, dst_ip, IP_PROTO_UDP,
|
||||
q->tot_len, UDP_HLEN);
|
||||
acc = udpchksum + (u16_t)~(chksum);
|
||||
udpchksum = FOLD_U32T(acc);
|
||||
} else
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
{
|
||||
udpchksum = inet_chksum_pseudo(q, src_ip, dst_ip, IP_PROTO_UDP, q->tot_len);
|
||||
}
|
||||
|
||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||
if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
|
||||
if (udpchksum == 0x0000) {
|
||||
udpchksum = 0xffff;
|
||||
}
|
||||
udphdr->chksum = udpchksum;
|
||||
}
|
||||
#endif /* CHECKSUM_CHECK_UDP */
|
||||
#endif /* CHECKSUM_GEN_UDP */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum));
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n"));
|
||||
/* output to IP */
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
netif->addr_hint = &(pcb->addr_hint);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint);
|
||||
err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
netif->addr_hint = NULL;
|
||||
#endif /* LWIP_NETIF_HWADDRHINT*/
|
||||
NETIF_SET_HWADDRHINT(netif, NULL);
|
||||
}
|
||||
/* TODO: must this be increased even if error occured? */
|
||||
snmp_inc_udpoutdatagrams();
|
||||
@@ -576,7 +763,7 @@ udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
|
||||
* @see udp_disconnect()
|
||||
*/
|
||||
err_t
|
||||
udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
||||
udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
||||
{
|
||||
struct udp_pcb *ipcb;
|
||||
u8_t rebind;
|
||||
@@ -596,13 +783,16 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
||||
rebind = 1;
|
||||
}
|
||||
|
||||
/* this code does not allow upper layer to share a UDP port for
|
||||
listening to broadcast or multicast traffic (See SO_REUSE_ADDR and
|
||||
SO_REUSE_PORT under *BSD). TODO: See where it fits instead, OR
|
||||
combine with implementation of UDP PCB flags. Leon Woestenberg. */
|
||||
#ifdef LWIP_UDP_TODO
|
||||
/* port matches that of PCB in list? */
|
||||
else
|
||||
/* By default, we don't allow to bind to a port that any other udp
|
||||
PCB is alread bound to, unless *all* PCBs with that port have tha
|
||||
REUSEADDR flag set. */
|
||||
#if SO_REUSE
|
||||
else if (!ip_get_option(pcb, SOF_REUSEADDR) &&
|
||||
!ip_get_option(ipcb, SOF_REUSEADDR)) {
|
||||
#else /* SO_REUSE */
|
||||
/* port matches that of PCB in list and REUSEADDR not set -> reject */
|
||||
else {
|
||||
#endif /* SO_REUSE */
|
||||
if ((ipcb->local_port == port) &&
|
||||
/* IP address matches, or one is IP_ADDR_ANY? */
|
||||
(ip_addr_isany(&(ipcb->local_ip)) ||
|
||||
@@ -613,30 +803,15 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
||||
("udp_bind: local port %"U16_F" already bound by another pcb\n", port));
|
||||
return ERR_USE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
ip_addr_set(&pcb->local_ip, ipaddr);
|
||||
|
||||
/* no port specified? */
|
||||
if (port == 0) {
|
||||
#ifndef UDP_LOCAL_PORT_RANGE_START
|
||||
#define UDP_LOCAL_PORT_RANGE_START 4096
|
||||
#define UDP_LOCAL_PORT_RANGE_END 0x7fff
|
||||
#endif
|
||||
port = UDP_LOCAL_PORT_RANGE_START;
|
||||
ipcb = udp_pcbs;
|
||||
while ((ipcb != NULL) && (port != UDP_LOCAL_PORT_RANGE_END)) {
|
||||
if (ipcb->local_port == port) {
|
||||
/* port is already used by another udp_pcb */
|
||||
port++;
|
||||
/* restart scanning all udp pcbs */
|
||||
ipcb = udp_pcbs;
|
||||
} else
|
||||
/* go on with next udp pcb */
|
||||
ipcb = ipcb->next;
|
||||
}
|
||||
if (ipcb != NULL) {
|
||||
port = udp_new_port();
|
||||
if (port == 0) {
|
||||
/* no more ports available in local range */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n"));
|
||||
return ERR_USE;
|
||||
@@ -652,10 +827,9 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
||||
}
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||
("udp_bind: bound to %"U16_F".%"U16_F".%"U16_F".%"U16_F", port %"U16_F"\n",
|
||||
(u16_t)((ntohl(pcb->local_ip.addr) >> 24) & 0xff),
|
||||
(u16_t)((ntohl(pcb->local_ip.addr) >> 16) & 0xff),
|
||||
(u16_t)((ntohl(pcb->local_ip.addr) >> 8) & 0xff),
|
||||
(u16_t)(ntohl(pcb->local_ip.addr) & 0xff), pcb->local_port));
|
||||
ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip),
|
||||
ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip),
|
||||
pcb->local_port));
|
||||
return ERR_OK;
|
||||
}
|
||||
/**
|
||||
@@ -676,14 +850,15 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
||||
* @see udp_disconnect()
|
||||
*/
|
||||
err_t
|
||||
udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
||||
udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
|
||||
{
|
||||
struct udp_pcb *ipcb;
|
||||
|
||||
if (pcb->local_port == 0) {
|
||||
err_t err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);
|
||||
if (err != ERR_OK)
|
||||
if (err != ERR_OK) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
ip_addr_set(&pcb->remote_ip, ipaddr);
|
||||
@@ -710,10 +885,9 @@ udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
||||
#endif
|
||||
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
|
||||
("udp_connect: connected to %"U16_F".%"U16_F".%"U16_F".%"U16_F",port %"U16_F"\n",
|
||||
(u16_t)((ntohl(pcb->remote_ip.addr) >> 24) & 0xff),
|
||||
(u16_t)((ntohl(pcb->remote_ip.addr) >> 16) & 0xff),
|
||||
(u16_t)((ntohl(pcb->remote_ip.addr) >> 8) & 0xff),
|
||||
(u16_t)(ntohl(pcb->remote_ip.addr) & 0xff), pcb->remote_port));
|
||||
ip4_addr1_16(&pcb->local_ip), ip4_addr2_16(&pcb->local_ip),
|
||||
ip4_addr3_16(&pcb->local_ip), ip4_addr4_16(&pcb->local_ip),
|
||||
pcb->local_port));
|
||||
|
||||
/* Insert UDP PCB into the list of active UDP PCBs. */
|
||||
for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
|
||||
@@ -737,7 +911,7 @@ void
|
||||
udp_disconnect(struct udp_pcb *pcb)
|
||||
{
|
||||
/* reset remote address association */
|
||||
ip_addr_set(&pcb->remote_ip, IP_ADDR_ANY);
|
||||
ip_addr_set_any(&pcb->remote_ip);
|
||||
pcb->remote_port = 0;
|
||||
/* mark PCB as unconnected */
|
||||
pcb->flags &= ~UDP_FLAGS_CONNECTED;
|
||||
@@ -753,10 +927,7 @@ udp_disconnect(struct udp_pcb *pcb)
|
||||
* @param recv_arg additional argument to pass to the callback function
|
||||
*/
|
||||
void
|
||||
udp_recv(struct udp_pcb *pcb,
|
||||
void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p,
|
||||
struct ip_addr *addr, u16_t port),
|
||||
void *recv_arg)
|
||||
udp_recv(struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg)
|
||||
{
|
||||
/* remember recv() callback and user data */
|
||||
pcb->recv = recv;
|
||||
@@ -782,7 +953,7 @@ udp_remove(struct udp_pcb *pcb)
|
||||
/* make list start at 2nd pcb */
|
||||
udp_pcbs = udp_pcbs->next;
|
||||
/* pcb not 1st in list */
|
||||
} else
|
||||
} else {
|
||||
for (pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
|
||||
/* find pcb in udp_pcbs list */
|
||||
if (pcb2->next != NULL && pcb2->next == pcb) {
|
||||
@@ -790,6 +961,7 @@ udp_remove(struct udp_pcb *pcb)
|
||||
pcb2->next = pcb->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
memp_free(MEMP_UDP_PCB, pcb);
|
||||
}
|
||||
|
||||
@@ -805,7 +977,7 @@ struct udp_pcb *
|
||||
udp_new(void)
|
||||
{
|
||||
struct udp_pcb *pcb;
|
||||
pcb = memp_malloc(MEMP_UDP_PCB);
|
||||
pcb = (struct udp_pcb *)memp_malloc(MEMP_UDP_PCB);
|
||||
/* could allocate UDP PCB? */
|
||||
if (pcb != NULL) {
|
||||
/* UDP Lite: by initializing to all zeroes, chksum_len is set to 0
|
||||
|
||||
@@ -80,7 +80,7 @@ extern "C" {
|
||||
|
||||
struct autoip
|
||||
{
|
||||
struct ip_addr llipaddr; /* the currently selected, probed, announced or used LL IP-Address */
|
||||
ip_addr_t llipaddr; /* the currently selected, probed, announced or used LL IP-Address */
|
||||
u8_t state; /* current AutoIP state machine state */
|
||||
u8_t sent_num; /* sent number of probes or announces, dependent on state */
|
||||
u16_t ttw; /* ticks to wait, tick is AUTOIP_TMR_INTERVAL long */
|
||||
@@ -89,8 +89,10 @@ struct autoip
|
||||
};
|
||||
|
||||
|
||||
/** Init srand, has to be called before entering mainloop */
|
||||
void autoip_init(void);
|
||||
#define autoip_init() /* Compatibility define, no init needed. */
|
||||
|
||||
/** Set a struct autoip allocated by the application to work with */
|
||||
void autoip_set_struct(struct netif *netif, struct autoip *autoip);
|
||||
|
||||
/** Start AutoIP client */
|
||||
err_t autoip_start(struct netif *netif);
|
||||
|
||||
@@ -41,29 +41,29 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ICMP_ER 0 /* echo reply */
|
||||
#define ICMP_DUR 3 /* destination unreachable */
|
||||
#define ICMP_SQ 4 /* source quench */
|
||||
#define ICMP_RD 5 /* redirect */
|
||||
#define ICMP_ER 0 /* echo reply */
|
||||
#define ICMP_DUR 3 /* destination unreachable */
|
||||
#define ICMP_SQ 4 /* source quench */
|
||||
#define ICMP_RD 5 /* redirect */
|
||||
#define ICMP_ECHO 8 /* echo */
|
||||
#define ICMP_TE 11 /* time exceeded */
|
||||
#define ICMP_PP 12 /* parameter problem */
|
||||
#define ICMP_TS 13 /* timestamp */
|
||||
#define ICMP_TE 11 /* time exceeded */
|
||||
#define ICMP_PP 12 /* parameter problem */
|
||||
#define ICMP_TS 13 /* timestamp */
|
||||
#define ICMP_TSR 14 /* timestamp reply */
|
||||
#define ICMP_IRQ 15 /* information request */
|
||||
#define ICMP_IR 16 /* information reply */
|
||||
#define ICMP_IR 16 /* information reply */
|
||||
|
||||
enum icmp_dur_type {
|
||||
ICMP_DUR_NET = 0, /* net unreachable */
|
||||
ICMP_DUR_HOST = 1, /* host unreachable */
|
||||
ICMP_DUR_NET = 0, /* net unreachable */
|
||||
ICMP_DUR_HOST = 1, /* host unreachable */
|
||||
ICMP_DUR_PROTO = 2, /* protocol unreachable */
|
||||
ICMP_DUR_PORT = 3, /* port unreachable */
|
||||
ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */
|
||||
ICMP_DUR_SR = 5 /* source route failed */
|
||||
ICMP_DUR_PORT = 3, /* port unreachable */
|
||||
ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */
|
||||
ICMP_DUR_SR = 5 /* source route failed */
|
||||
};
|
||||
|
||||
enum icmp_te_type {
|
||||
ICMP_TE_TTL = 0, /* time to live exceeded in transit */
|
||||
ICMP_TE_TTL = 0, /* time to live exceeded in transit */
|
||||
ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */
|
||||
};
|
||||
|
||||
|
||||
@@ -46,57 +46,20 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* IGMP constants
|
||||
*/
|
||||
#define IP_PROTO_IGMP 2
|
||||
#define IGMP_TTL 1
|
||||
#define IGMP_MINLEN 8
|
||||
#define ROUTER_ALERT 0x9404
|
||||
#define ROUTER_ALERTLEN 4
|
||||
|
||||
/*
|
||||
* IGMP message types, including version number.
|
||||
*/
|
||||
#define IGMP_MEMB_QUERY 0x11 /* Membership query */
|
||||
#define IGMP_V1_MEMB_REPORT 0x12 /* Ver. 1 membership report */
|
||||
#define IGMP_V2_MEMB_REPORT 0x16 /* Ver. 2 membership report */
|
||||
#define IGMP_LEAVE_GROUP 0x17 /* Leave-group message */
|
||||
|
||||
/* IGMP timer */
|
||||
#define IGMP_TMR_INTERVAL 100 /* Milliseconds */
|
||||
#define IGMP_V1_DELAYING_MEMBER_TMR (1000/IGMP_TMR_INTERVAL)
|
||||
#define IGMP_JOIN_DELAYING_MEMBER_TMR (500 /IGMP_TMR_INTERVAL)
|
||||
|
||||
/* MAC Filter Actions */
|
||||
/* MAC Filter Actions, these are passed to a netif's
|
||||
* igmp_mac_filter callback function. */
|
||||
#define IGMP_DEL_MAC_FILTER 0
|
||||
#define IGMP_ADD_MAC_FILTER 1
|
||||
|
||||
/* Group membership states */
|
||||
#define IGMP_GROUP_NON_MEMBER 0
|
||||
#define IGMP_GROUP_DELAYING_MEMBER 1
|
||||
#define IGMP_GROUP_IDLE_MEMBER 2
|
||||
|
||||
/*
|
||||
* IGMP packet format.
|
||||
*/
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct igmp_msg {
|
||||
PACK_STRUCT_FIELD(u8_t igmp_msgtype);
|
||||
PACK_STRUCT_FIELD(u8_t igmp_maxresp);
|
||||
PACK_STRUCT_FIELD(u16_t igmp_checksum);
|
||||
PACK_STRUCT_FIELD(struct ip_addr igmp_group_address);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* now a group structure - there is
|
||||
/**
|
||||
* igmp group structure - there is
|
||||
* a list of groups for each interface
|
||||
* these should really be linked from the interface, but
|
||||
* if we keep them separate we will not affect the lwip original code
|
||||
@@ -106,53 +69,34 @@ PACK_STRUCT_END
|
||||
* will not run the state machine as it is used to kick off reports
|
||||
* from all the other groups
|
||||
*/
|
||||
|
||||
struct igmp_group {
|
||||
/** next link */
|
||||
struct igmp_group *next;
|
||||
struct netif *interface;
|
||||
struct ip_addr group_address;
|
||||
u8_t last_reporter_flag; /* signifies we were the last person to report */
|
||||
/** interface on which the group is active */
|
||||
struct netif *netif;
|
||||
/** multicast address */
|
||||
ip_addr_t group_address;
|
||||
/** signifies we were the last person to report */
|
||||
u8_t last_reporter_flag;
|
||||
/** current state of the group */
|
||||
u8_t group_state;
|
||||
/** timer for reporting, negative is OFF */
|
||||
u16_t timer;
|
||||
u8_t use; /* counter of simultaneous uses */
|
||||
/** counter of simultaneous uses */
|
||||
u8_t use;
|
||||
};
|
||||
|
||||
|
||||
/* Prototypes */
|
||||
void igmp_init(void);
|
||||
|
||||
err_t igmp_start( struct netif *netif);
|
||||
|
||||
err_t igmp_stop( struct netif *netif);
|
||||
|
||||
void igmp_report_groups( struct netif *netif);
|
||||
|
||||
struct igmp_group *igmp_lookfor_group( struct netif *ifp, struct ip_addr *addr);
|
||||
|
||||
struct igmp_group *igmp_lookup_group( struct netif *ifp, struct ip_addr *addr);
|
||||
|
||||
err_t igmp_remove_group( struct igmp_group *group);
|
||||
|
||||
void igmp_input( struct pbuf *p, struct netif *inp, struct ip_addr *dest);
|
||||
|
||||
err_t igmp_joingroup( struct ip_addr *ifaddr, struct ip_addr *groupaddr);
|
||||
|
||||
err_t igmp_leavegroup( struct ip_addr *ifaddr, struct ip_addr *groupaddr);
|
||||
|
||||
err_t igmp_start(struct netif *netif);
|
||||
err_t igmp_stop(struct netif *netif);
|
||||
void igmp_report_groups(struct netif *netif);
|
||||
struct igmp_group *igmp_lookfor_group(struct netif *ifp, ip_addr_t *addr);
|
||||
void igmp_input(struct pbuf *p, struct netif *inp, ip_addr_t *dest);
|
||||
err_t igmp_joingroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr);
|
||||
err_t igmp_leavegroup(ip_addr_t *ifaddr, ip_addr_t *groupaddr);
|
||||
void igmp_tmr(void);
|
||||
|
||||
void igmp_timeout( struct igmp_group *group);
|
||||
|
||||
void igmp_start_timer( struct igmp_group *group, u8_t max_time);
|
||||
|
||||
void igmp_stop_timer( struct igmp_group *group);
|
||||
|
||||
void igmp_delaying_member( struct igmp_group *group, u8_t maxresp);
|
||||
|
||||
err_t igmp_ip_output_if( struct pbuf *p, struct ip_addr *src, struct ip_addr *dest, u8_t ttl, u8_t proto, struct netif *netif);
|
||||
|
||||
void igmp_send( struct igmp_group *group, u8_t type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -33,68 +33,72 @@
|
||||
#define __LWIP_INET_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* For compatibility with BSD code */
|
||||
/** For compatibility with BSD code */
|
||||
struct in_addr {
|
||||
u32_t s_addr;
|
||||
};
|
||||
|
||||
#define INADDR_NONE ((u32_t)0xffffffffUL) /* 255.255.255.255 */
|
||||
#define INADDR_LOOPBACK ((u32_t)0x7f000001UL) /* 127.0.0.1 */
|
||||
#define INADDR_ANY ((u32_t)0x00000000UL) /* 0.0.0.0 */
|
||||
#define INADDR_BROADCAST ((u32_t)0xffffffffUL) /* 255.255.255.255 */
|
||||
/** 255.255.255.255 */
|
||||
#define INADDR_NONE IPADDR_NONE
|
||||
/** 127.0.0.1 */
|
||||
#define INADDR_LOOPBACK IPADDR_LOOPBACK
|
||||
/** 0.0.0.0 */
|
||||
#define INADDR_ANY IPADDR_ANY
|
||||
/** 255.255.255.255 */
|
||||
#define INADDR_BROADCAST IPADDR_BROADCAST
|
||||
|
||||
u32_t inet_addr(const char *cp);
|
||||
int inet_aton(const char *cp, struct in_addr *addr);
|
||||
char *inet_ntoa(struct in_addr addr); /* returns ptr to static buffer; not reentrant! */
|
||||
/* Definitions of the bits in an Internet address integer.
|
||||
|
||||
#ifdef htons
|
||||
#undef htons
|
||||
#endif /* htons */
|
||||
#ifdef htonl
|
||||
#undef htonl
|
||||
#endif /* htonl */
|
||||
#ifdef ntohs
|
||||
#undef ntohs
|
||||
#endif /* ntohs */
|
||||
#ifdef ntohl
|
||||
#undef ntohl
|
||||
#endif /* ntohl */
|
||||
On subnets, host and network parts are found according to
|
||||
the subnet mask, not these masks. */
|
||||
#define IN_CLASSA(a) IP_CLASSA(a)
|
||||
#define IN_CLASSA_NET IP_CLASSA_NET
|
||||
#define IN_CLASSA_NSHIFT IP_CLASSA_NSHIFT
|
||||
#define IN_CLASSA_HOST IP_CLASSA_HOST
|
||||
#define IN_CLASSA_MAX IP_CLASSA_MAX
|
||||
|
||||
#ifndef LWIP_PLATFORM_BYTESWAP
|
||||
#define LWIP_PLATFORM_BYTESWAP 0
|
||||
#endif
|
||||
#define IN_CLASSB(b) IP_CLASSB(b)
|
||||
#define IN_CLASSB_NET IP_CLASSB_NET
|
||||
#define IN_CLASSB_NSHIFT IP_CLASSB_NSHIFT
|
||||
#define IN_CLASSB_HOST IP_CLASSB_HOST
|
||||
#define IN_CLASSB_MAX IP_CLASSB_MAX
|
||||
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
#define htons(x) (x)
|
||||
#define ntohs(x) (x)
|
||||
#define htonl(x) (x)
|
||||
#define ntohl(x) (x)
|
||||
#else /* BYTE_ORDER != BIG_ENDIAN */
|
||||
#ifdef LWIP_PREFIX_BYTEORDER_FUNCS
|
||||
/* workaround for naming collisions on some platforms */
|
||||
#define htons lwip_htons
|
||||
#define ntohs lwip_ntohs
|
||||
#define htonl lwip_htonl
|
||||
#define ntohl lwip_ntohl
|
||||
#endif /* LWIP_PREFIX_BYTEORDER_FUNCS */
|
||||
#if LWIP_PLATFORM_BYTESWAP
|
||||
#define htons(x) LWIP_PLATFORM_HTONS(x)
|
||||
#define ntohs(x) LWIP_PLATFORM_HTONS(x)
|
||||
#define htonl(x) LWIP_PLATFORM_HTONL(x)
|
||||
#define ntohl(x) LWIP_PLATFORM_HTONL(x)
|
||||
#else /* LWIP_PLATFORM_BYTESWAP */
|
||||
u16_t htons(u16_t x);
|
||||
u16_t ntohs(u16_t x);
|
||||
u32_t htonl(u32_t x);
|
||||
u32_t ntohl(u32_t x);
|
||||
#endif /* LWIP_PLATFORM_BYTESWAP */
|
||||
#define IN_CLASSC(c) IP_CLASSC(c)
|
||||
#define IN_CLASSC_NET IP_CLASSC_NET
|
||||
#define IN_CLASSC_NSHIFT IP_CLASSC_NSHIFT
|
||||
#define IN_CLASSC_HOST IP_CLASSC_HOST
|
||||
#define IN_CLASSC_MAX IP_CLASSC_MAX
|
||||
|
||||
#endif /* BYTE_ORDER == BIG_ENDIAN */
|
||||
#define IN_CLASSD(d) IP_CLASSD(d)
|
||||
#define IN_CLASSD_NET IP_CLASSD_NET /* These ones aren't really */
|
||||
#define IN_CLASSD_NSHIFT IP_CLASSD_NSHIFT /* net and host fields, but */
|
||||
#define IN_CLASSD_HOST IP_CLASSD_HOST /* routing needn't know. */
|
||||
#define IN_CLASSD_MAX IP_CLASSD_MAX
|
||||
|
||||
#define IN_MULTICAST(a) IP_MULTICAST(a)
|
||||
|
||||
#define IN_EXPERIMENTAL(a) IP_EXPERIMENTAL(a)
|
||||
#define IN_BADCLASS(a) IP_BADCLASS(a)
|
||||
|
||||
#define IN_LOOPBACKNET IP_LOOPBACKNET
|
||||
|
||||
#define inet_addr_from_ipaddr(target_inaddr, source_ipaddr) ((target_inaddr)->s_addr = ip4_addr_get_u32(source_ipaddr))
|
||||
#define inet_addr_to_ipaddr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr))
|
||||
/* ATTENTION: the next define only works because both s_addr and ip_addr_t are an u32_t effectively! */
|
||||
#define inet_addr_to_ipaddr_p(target_ipaddr_p, source_inaddr) ((target_ipaddr_p) = (ip_addr_t*)&((source_inaddr)->s_addr))
|
||||
|
||||
/* directly map this to the lwip internal functions */
|
||||
#define inet_addr(cp) ipaddr_addr(cp)
|
||||
#define inet_aton(cp, addr) ipaddr_aton(cp, (ip_addr_t*)addr)
|
||||
#define inet_ntoa(addr) ipaddr_ntoa((ip_addr_t*)&(addr))
|
||||
#define inet_ntoa_r(addr, buf, buflen) ipaddr_ntoa_r((ip_addr_t*)&(addr), buf, buflen)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -37,6 +37,35 @@
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
/** Swap the bytes in an u16_t: much like htons() for little-endian */
|
||||
#ifndef SWAP_BYTES_IN_WORD
|
||||
#if LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
/* little endian and PLATFORM_BYTESWAP defined */
|
||||
#define SWAP_BYTES_IN_WORD(w) LWIP_PLATFORM_HTONS(w)
|
||||
#else /* LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN) */
|
||||
/* can't use htons on big endian (or PLATFORM_BYTESWAP not defined)... */
|
||||
#define SWAP_BYTES_IN_WORD(w) (((w) & 0xff) << 8) | (((w) & 0xff00) >> 8)
|
||||
#endif /* LWIP_PLATFORM_BYTESWAP && (BYTE_ORDER == LITTLE_ENDIAN)*/
|
||||
#endif /* SWAP_BYTES_IN_WORD */
|
||||
|
||||
/** Split an u32_t in two u16_ts and add them up */
|
||||
#ifndef FOLD_U32T
|
||||
#define FOLD_U32T(u) (((u) >> 16) + ((u) & 0x0000ffffUL))
|
||||
#endif
|
||||
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
/** Function-like macro: same as MEMCPY but returns the checksum of copied data
|
||||
as u16_t */
|
||||
#ifndef LWIP_CHKSUM_COPY
|
||||
#define LWIP_CHKSUM_COPY(dst, src, len) lwip_chksum_copy(dst, src, len)
|
||||
#ifndef LWIP_CHKSUM_COPY_ALGORITHM
|
||||
#define LWIP_CHKSUM_COPY_ALGORITHM 1
|
||||
#endif /* LWIP_CHKSUM_COPY_ALGORITHM */
|
||||
#endif /* LWIP_CHKSUM_COPY */
|
||||
#else /* LWIP_CHECKSUM_ON_COPY */
|
||||
#define LWIP_CHKSUM_COPY_ALGORITHM 0
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -44,13 +73,14 @@ extern "C" {
|
||||
u16_t inet_chksum(void *dataptr, u16_t len);
|
||||
u16_t inet_chksum_pbuf(struct pbuf *p);
|
||||
u16_t inet_chksum_pseudo(struct pbuf *p,
|
||||
struct ip_addr *src, struct ip_addr *dest,
|
||||
ip_addr_t *src, ip_addr_t *dest,
|
||||
u8_t proto, u16_t proto_len);
|
||||
#if LWIP_UDPLITE
|
||||
u16_t inet_chksum_pseudo_partial(struct pbuf *p,
|
||||
struct ip_addr *src, struct ip_addr *dest,
|
||||
ip_addr_t *src, ip_addr_t *dest,
|
||||
u8_t proto, u16_t proto_len, u16_t chksum_len);
|
||||
#endif
|
||||
#if LWIP_CHKSUM_COPY_ALGORITHM
|
||||
u16_t lwip_chksum_copy(void *dst, const void *src, u16_t len);
|
||||
#endif /* LWIP_CHKSUM_COPY_ALGORITHM */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ extern "C" {
|
||||
#define IP_HLEN 20
|
||||
|
||||
#define IP_PROTO_ICMP 1
|
||||
#define IP_PROTO_IGMP 2
|
||||
#define IP_PROTO_UDP 17
|
||||
#define IP_PROTO_UDPLITE 136
|
||||
#define IP_PROTO_TCP 6
|
||||
@@ -74,10 +75,10 @@ extern "C" {
|
||||
having to change all PCB structs. */
|
||||
#define IP_PCB \
|
||||
/* ip addresses in network byte order */ \
|
||||
struct ip_addr local_ip; \
|
||||
struct ip_addr remote_ip; \
|
||||
ip_addr_t local_ip; \
|
||||
ip_addr_t remote_ip; \
|
||||
/* Socket options */ \
|
||||
u16_t so_options; \
|
||||
u8_t so_options; \
|
||||
/* Type Of Service */ \
|
||||
u8_t tos; \
|
||||
/* Time To Live */ \
|
||||
@@ -93,16 +94,19 @@ struct ip_pcb {
|
||||
/*
|
||||
* Option flags per-socket. These are the same like SO_XXX.
|
||||
*/
|
||||
#define SOF_DEBUG (u16_t)0x0001U /* turn on debugging info recording */
|
||||
#define SOF_ACCEPTCONN (u16_t)0x0002U /* socket has had listen() */
|
||||
#define SOF_REUSEADDR (u16_t)0x0004U /* allow local address reuse */
|
||||
#define SOF_KEEPALIVE (u16_t)0x0008U /* keep connections alive */
|
||||
#define SOF_DONTROUTE (u16_t)0x0010U /* just use interface addresses */
|
||||
#define SOF_BROADCAST (u16_t)0x0020U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */
|
||||
#define SOF_USELOOPBACK (u16_t)0x0040U /* bypass hardware when possible */
|
||||
#define SOF_LINGER (u16_t)0x0080U /* linger on close if data present */
|
||||
#define SOF_OOBINLINE (u16_t)0x0100U /* leave received OOB data in line */
|
||||
#define SOF_REUSEPORT (u16_t)0x0200U /* allow local address & port reuse */
|
||||
/*#define SOF_DEBUG 0x01U Unimplemented: turn on debugging info recording */
|
||||
#define SOF_ACCEPTCONN 0x02U /* socket has had listen() */
|
||||
#define SOF_REUSEADDR 0x04U /* allow local address reuse */
|
||||
#define SOF_KEEPALIVE 0x08U /* keep connections alive */
|
||||
/*#define SOF_DONTROUTE 0x10U Unimplemented: just use interface addresses */
|
||||
#define SOF_BROADCAST 0x20U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */
|
||||
/*#define SOF_USELOOPBACK 0x40U Unimplemented: bypass hardware when possible */
|
||||
#define SOF_LINGER 0x80U /* linger on close if data present */
|
||||
/*#define SOF_OOBINLINE 0x0100U Unimplemented: leave received OOB data in line */
|
||||
/*#define SOF_REUSEPORT 0x0200U Unimplemented: allow local address & port reuse */
|
||||
|
||||
/* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */
|
||||
#define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE|SOF_LINGER/*|SOF_DEBUG|SOF_DONTROUTE|SOF_OOBINLINE*/)
|
||||
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
@@ -110,68 +114,77 @@ struct ip_pcb {
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct ip_hdr {
|
||||
/* version / header length / type of service */
|
||||
PACK_STRUCT_FIELD(u16_t _v_hl_tos);
|
||||
/* version / header length */
|
||||
PACK_STRUCT_FIELD(u8_t _v_hl);
|
||||
/* type of service */
|
||||
PACK_STRUCT_FIELD(u8_t _tos);
|
||||
/* total length */
|
||||
PACK_STRUCT_FIELD(u16_t _len);
|
||||
/* identification */
|
||||
PACK_STRUCT_FIELD(u16_t _id);
|
||||
/* fragment offset field */
|
||||
PACK_STRUCT_FIELD(u16_t _offset);
|
||||
#define IP_RF 0x8000 /* reserved fragment flag */
|
||||
#define IP_DF 0x4000 /* dont fragment flag */
|
||||
#define IP_MF 0x2000 /* more fragments flag */
|
||||
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
|
||||
/* time to live / protocol*/
|
||||
PACK_STRUCT_FIELD(u16_t _ttl_proto);
|
||||
#define IP_RF 0x8000U /* reserved fragment flag */
|
||||
#define IP_DF 0x4000U /* dont fragment flag */
|
||||
#define IP_MF 0x2000U /* more fragments flag */
|
||||
#define IP_OFFMASK 0x1fffU /* mask for fragmenting bits */
|
||||
/* time to live */
|
||||
PACK_STRUCT_FIELD(u8_t _ttl);
|
||||
/* protocol*/
|
||||
PACK_STRUCT_FIELD(u8_t _proto);
|
||||
/* checksum */
|
||||
PACK_STRUCT_FIELD(u16_t _chksum);
|
||||
/* source and destination IP addresses */
|
||||
PACK_STRUCT_FIELD(struct ip_addr src);
|
||||
PACK_STRUCT_FIELD(struct ip_addr dest);
|
||||
PACK_STRUCT_FIELD(ip_addr_p_t src);
|
||||
PACK_STRUCT_FIELD(ip_addr_p_t dest);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#define IPH_V(hdr) (ntohs((hdr)->_v_hl_tos) >> 12)
|
||||
#define IPH_HL(hdr) ((ntohs((hdr)->_v_hl_tos) >> 8) & 0x0f)
|
||||
#define IPH_TOS(hdr) (ntohs((hdr)->_v_hl_tos) & 0xff)
|
||||
#define IPH_V(hdr) ((hdr)->_v_hl >> 4)
|
||||
#define IPH_HL(hdr) ((hdr)->_v_hl & 0x0f)
|
||||
#define IPH_TOS(hdr) ((hdr)->_tos)
|
||||
#define IPH_LEN(hdr) ((hdr)->_len)
|
||||
#define IPH_ID(hdr) ((hdr)->_id)
|
||||
#define IPH_OFFSET(hdr) ((hdr)->_offset)
|
||||
#define IPH_TTL(hdr) (ntohs((hdr)->_ttl_proto) >> 8)
|
||||
#define IPH_PROTO(hdr) (ntohs((hdr)->_ttl_proto) & 0xff)
|
||||
#define IPH_TTL(hdr) ((hdr)->_ttl)
|
||||
#define IPH_PROTO(hdr) ((hdr)->_proto)
|
||||
#define IPH_CHKSUM(hdr) ((hdr)->_chksum)
|
||||
|
||||
#define IPH_VHLTOS_SET(hdr, v, hl, tos) (hdr)->_v_hl_tos = (htons(((v) << 12) | ((hl) << 8) | (tos)))
|
||||
#define IPH_VHL_SET(hdr, v, hl) (hdr)->_v_hl = (((v) << 4) | (hl))
|
||||
#define IPH_TOS_SET(hdr, tos) (hdr)->_tos = (tos)
|
||||
#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len)
|
||||
#define IPH_ID_SET(hdr, id) (hdr)->_id = (id)
|
||||
#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off)
|
||||
#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl_proto = (htons(IPH_PROTO(hdr) | ((u16_t)(ttl) << 8)))
|
||||
#define IPH_PROTO_SET(hdr, proto) (hdr)->_ttl_proto = (htons((proto) | (IPH_TTL(hdr) << 8)))
|
||||
#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl = (u8_t)(ttl)
|
||||
#define IPH_PROTO_SET(hdr, proto) (hdr)->_proto = (u8_t)(proto)
|
||||
#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum)
|
||||
|
||||
/** The interface that provided the packet for the current callback invocation. */
|
||||
extern struct netif *current_netif;
|
||||
/** Header of the input packet currently being processed. */
|
||||
extern const struct ip_hdr *current_header;
|
||||
/** Source IP address of current_header */
|
||||
extern ip_addr_t current_iphdr_src;
|
||||
/** Destination IP address of current_header */
|
||||
extern ip_addr_t current_iphdr_dest;
|
||||
|
||||
#define ip_init() /* Compatibility define, not init needed. */
|
||||
struct netif *ip_route(struct ip_addr *dest);
|
||||
struct netif *ip_route(ip_addr_t *dest);
|
||||
err_t ip_input(struct pbuf *p, struct netif *inp);
|
||||
err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
err_t ip_output(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto);
|
||||
err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
err_t ip_output_if(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto,
|
||||
struct netif *netif);
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
err_t ip_output_hinted(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
err_t ip_output_hinted(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto, u8_t *addr_hint);
|
||||
#endif /* LWIP_NETIF_HWADDRHINT */
|
||||
#if IP_OPTIONS_SEND
|
||||
err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto, struct netif *netif, void *ip_options,
|
||||
u16_t optlen);
|
||||
#endif /* IP_OPTIONS_SEND */
|
||||
@@ -183,6 +196,18 @@ err_t ip_output_if_opt(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest
|
||||
* This function must only be called from a receive callback (udp_recv,
|
||||
* raw_recv, tcp_accept). It will return NULL otherwise. */
|
||||
#define ip_current_header() (current_header)
|
||||
/** Source IP address of current_header */
|
||||
#define ip_current_src_addr() (¤t_iphdr_src)
|
||||
/** Destination IP address of current_header */
|
||||
#define ip_current_dest_addr() (¤t_iphdr_dest)
|
||||
|
||||
/** Gets an IP pcb option (SOF_* flags) */
|
||||
#define ip_get_option(pcb, opt) ((pcb)->so_options & (opt))
|
||||
/** Sets an IP pcb option (SOF_* flags) */
|
||||
#define ip_set_option(pcb, opt) ((pcb)->so_options |= (opt))
|
||||
/** Resets an IP pcb option (SOF_* flags) */
|
||||
#define ip_reset_option(pcb, opt) ((pcb)->so_options &= ~(opt))
|
||||
|
||||
#if IP_DEBUG
|
||||
void ip_debug_print(struct pbuf *p);
|
||||
#else
|
||||
|
||||
@@ -33,18 +33,25 @@
|
||||
#define __LWIP_IP_ADDR_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/def.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* This is the aligned version of ip_addr_t,
|
||||
used as local variable, on the stack, etc. */
|
||||
struct ip_addr {
|
||||
u32_t addr;
|
||||
};
|
||||
|
||||
/* This is the packed version of ip_addr_t,
|
||||
used in network headers that are itself packed */
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct ip_addr {
|
||||
struct ip_addr_packed {
|
||||
PACK_STRUCT_FIELD(u32_t addr);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
@@ -52,6 +59,11 @@ PACK_STRUCT_END
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/** ip_addr_t uses a struct for convenience only, so that the same defines can
|
||||
* operate both on ip_addr_t as well as on ip_addr_p_t. */
|
||||
typedef struct ip_addr ip_addr_t;
|
||||
typedef struct ip_addr_packed ip_addr_p_t;
|
||||
|
||||
/*
|
||||
* struct ipaddr2 is used in the definition of the ARP packet format in
|
||||
* order to support compilers that don't have structure packing.
|
||||
@@ -68,59 +80,109 @@ PACK_STRUCT_END
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/* Forward declaration to not include netif.h */
|
||||
struct netif;
|
||||
|
||||
extern const struct ip_addr ip_addr_any;
|
||||
extern const struct ip_addr ip_addr_broadcast;
|
||||
extern const ip_addr_t ip_addr_any;
|
||||
extern const ip_addr_t ip_addr_broadcast;
|
||||
|
||||
/** IP_ADDR_ can be used as a fixed IP address
|
||||
* for the wildcard and the broadcast address
|
||||
*/
|
||||
#define IP_ADDR_ANY ((struct ip_addr *)&ip_addr_any)
|
||||
#define IP_ADDR_BROADCAST ((struct ip_addr *)&ip_addr_broadcast)
|
||||
#define IP_ADDR_ANY ((ip_addr_t *)&ip_addr_any)
|
||||
#define IP_ADDR_BROADCAST ((ip_addr_t *)&ip_addr_broadcast)
|
||||
|
||||
/** 255.255.255.255 */
|
||||
#define IPADDR_NONE ((u32_t)0xffffffffUL)
|
||||
/** 127.0.0.1 */
|
||||
#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL)
|
||||
/** 0.0.0.0 */
|
||||
#define IPADDR_ANY ((u32_t)0x00000000UL)
|
||||
/** 255.255.255.255 */
|
||||
#define IPADDR_BROADCAST ((u32_t)0xffffffffUL)
|
||||
|
||||
/* Definitions of the bits in an Internet address integer.
|
||||
|
||||
On subnets, host and network parts are found according to
|
||||
the subnet mask, not these masks. */
|
||||
#define IP_CLASSA(a) ((((u32_t)(a)) & 0x80000000UL) == 0)
|
||||
#define IP_CLASSA_NET 0xff000000
|
||||
#define IP_CLASSA_NSHIFT 24
|
||||
#define IP_CLASSA_HOST (0xffffffff & ~IP_CLASSA_NET)
|
||||
#define IP_CLASSA_MAX 128
|
||||
|
||||
#define IN_CLASSA(a) ((((u32_t)(a)) & 0x80000000UL) == 0)
|
||||
#define IN_CLASSA_NET 0xff000000
|
||||
#define IN_CLASSA_NSHIFT 24
|
||||
#define IN_CLASSA_HOST (0xffffffff & ~IN_CLASSA_NET)
|
||||
#define IN_CLASSA_MAX 128
|
||||
#define IP_CLASSB(a) ((((u32_t)(a)) & 0xc0000000UL) == 0x80000000UL)
|
||||
#define IP_CLASSB_NET 0xffff0000
|
||||
#define IP_CLASSB_NSHIFT 16
|
||||
#define IP_CLASSB_HOST (0xffffffff & ~IP_CLASSB_NET)
|
||||
#define IP_CLASSB_MAX 65536
|
||||
|
||||
#define IN_CLASSB(a) ((((u32_t)(a)) & 0xc0000000UL) == 0x80000000UL)
|
||||
#define IN_CLASSB_NET 0xffff0000
|
||||
#define IN_CLASSB_NSHIFT 16
|
||||
#define IN_CLASSB_HOST (0xffffffff & ~IN_CLASSB_NET)
|
||||
#define IN_CLASSB_MAX 65536
|
||||
#define IP_CLASSC(a) ((((u32_t)(a)) & 0xe0000000UL) == 0xc0000000UL)
|
||||
#define IP_CLASSC_NET 0xffffff00
|
||||
#define IP_CLASSC_NSHIFT 8
|
||||
#define IP_CLASSC_HOST (0xffffffff & ~IP_CLASSC_NET)
|
||||
|
||||
#define IN_CLASSC(a) ((((u32_t)(a)) & 0xe0000000UL) == 0xc0000000UL)
|
||||
#define IN_CLASSC_NET 0xffffff00
|
||||
#define IN_CLASSC_NSHIFT 8
|
||||
#define IN_CLASSC_HOST (0xffffffff & ~IN_CLASSC_NET)
|
||||
#define IP_CLASSD(a) (((u32_t)(a) & 0xf0000000UL) == 0xe0000000UL)
|
||||
#define IP_CLASSD_NET 0xf0000000 /* These ones aren't really */
|
||||
#define IP_CLASSD_NSHIFT 28 /* net and host fields, but */
|
||||
#define IP_CLASSD_HOST 0x0fffffff /* routing needn't know. */
|
||||
#define IP_MULTICAST(a) IP_CLASSD(a)
|
||||
|
||||
#define IN_CLASSD(a) (((u32_t)(a) & 0xf0000000UL) == 0xe0000000UL)
|
||||
#define IN_CLASSD_NET 0xf0000000 /* These ones aren't really */
|
||||
#define IN_CLASSD_NSHIFT 28 /* net and host fields, but */
|
||||
#define IN_CLASSD_HOST 0x0fffffff /* routing needn't know. */
|
||||
#define IN_MULTICAST(a) IN_CLASSD(a)
|
||||
#define IP_EXPERIMENTAL(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL)
|
||||
#define IP_BADCLASS(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL)
|
||||
|
||||
#define IN_EXPERIMENTAL(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL)
|
||||
#define IN_BADCLASS(a) (((u32_t)(a) & 0xf0000000UL) == 0xf0000000UL)
|
||||
#define IP_LOOPBACKNET 127 /* official! */
|
||||
|
||||
#define IN_LOOPBACKNET 127 /* official! */
|
||||
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
/** Set an IP address given by the four byte-parts */
|
||||
#define IP4_ADDR(ipaddr, a,b,c,d) \
|
||||
(ipaddr)->addr = htonl(((u32_t)((a) & 0xff) << 24) | \
|
||||
((u32_t)((b) & 0xff) << 16) | \
|
||||
((u32_t)((c) & 0xff) << 8) | \
|
||||
(u32_t)((d) & 0xff))
|
||||
(ipaddr)->addr = ((u32_t)((a) & 0xff) << 24) | \
|
||||
((u32_t)((b) & 0xff) << 16) | \
|
||||
((u32_t)((c) & 0xff) << 8) | \
|
||||
(u32_t)((d) & 0xff)
|
||||
#else
|
||||
/** Set an IP address given by the four byte-parts.
|
||||
Little-endian version that prevents the use of htonl. */
|
||||
#define IP4_ADDR(ipaddr, a,b,c,d) \
|
||||
(ipaddr)->addr = ((u32_t)((d) & 0xff) << 24) | \
|
||||
((u32_t)((c) & 0xff) << 16) | \
|
||||
((u32_t)((b) & 0xff) << 8) | \
|
||||
(u32_t)((a) & 0xff)
|
||||
#endif
|
||||
|
||||
/** MEMCPY-like copying of IP addresses where addresses are known to be
|
||||
* 16-bit-aligned if the port is correctly configured (so a port could define
|
||||
* this to copying 2 u16_t's) - no NULL-pointer-checking needed. */
|
||||
#ifndef IPADDR2_COPY
|
||||
#define IPADDR2_COPY(dest, src) SMEMCPY(dest, src, sizeof(ip_addr_t))
|
||||
#endif
|
||||
|
||||
/** Copy IP address - faster than ip_addr_set: no NULL check */
|
||||
#define ip_addr_copy(dest, src) ((dest).addr = (src).addr)
|
||||
/** Safely copy one IP address to another (src may be NULL) */
|
||||
#define ip_addr_set(dest, src) ((dest)->addr = \
|
||||
((src) == NULL ? 0 : \
|
||||
(src)->addr))
|
||||
/** Set complete address to zero */
|
||||
#define ip_addr_set_zero(ipaddr) ((ipaddr)->addr = 0)
|
||||
/** Set address to IPADDR_ANY (no need for htonl()) */
|
||||
#define ip_addr_set_any(ipaddr) ((ipaddr)->addr = IPADDR_ANY)
|
||||
/** Set address to loopback address */
|
||||
#define ip_addr_set_loopback(ipaddr) ((ipaddr)->addr = PP_HTONL(IPADDR_LOOPBACK))
|
||||
/** Safely copy one IP address to another and change byte order
|
||||
* from host- to network-order. */
|
||||
#define ip_addr_set_hton(dest, src) ((dest)->addr = \
|
||||
((src) == NULL ? 0:\
|
||||
htonl((src)->addr)))
|
||||
/** IPv4 only: set the IP address given as an u32_t */
|
||||
#define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32))
|
||||
/** IPv4 only: get the IP address as an u32_t */
|
||||
#define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr)
|
||||
|
||||
/** Get the network address by combining host address with netmask */
|
||||
#define ip_addr_get_network(target, host, netmask) ((target)->addr = ((host)->addr) & ((netmask)->addr))
|
||||
|
||||
#define ip_addr_set(dest, src) (dest)->addr = \
|
||||
((src) == NULL? 0:\
|
||||
(src)->addr)
|
||||
/**
|
||||
* Determine if two address are on the same network.
|
||||
*
|
||||
@@ -135,36 +197,45 @@ extern const struct ip_addr ip_addr_broadcast;
|
||||
(mask)->addr))
|
||||
#define ip_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr)
|
||||
|
||||
#define ip_addr_isany(addr1) ((addr1) == NULL || (addr1)->addr == 0)
|
||||
#define ip_addr_isany(addr1) ((addr1) == NULL || (addr1)->addr == IPADDR_ANY)
|
||||
|
||||
u8_t ip_addr_isbroadcast(struct ip_addr *, struct netif *);
|
||||
#define ip_addr_isbroadcast(ipaddr, netif) ip4_addr_isbroadcast((ipaddr)->addr, (netif))
|
||||
u8_t ip4_addr_isbroadcast(u32_t addr, const struct netif *netif);
|
||||
|
||||
#define ip_addr_ismulticast(addr1) (((addr1)->addr & ntohl(0xf0000000UL)) == ntohl(0xe0000000UL))
|
||||
#define ip_addr_netmask_valid(netmask) ip4_addr_netmask_valid((netmask)->addr)
|
||||
u8_t ip4_addr_netmask_valid(u32_t netmask);
|
||||
|
||||
#define ip_addr_islinklocal(addr1) (((addr1)->addr & ntohl(0xffff0000UL)) == ntohl(0xa9fe0000UL))
|
||||
#define ip_addr_ismulticast(addr1) (((addr1)->addr & PP_HTONL(0xf0000000UL)) == PP_HTONL(0xe0000000UL))
|
||||
|
||||
#define ip_addr_islinklocal(addr1) (((addr1)->addr & PP_HTONL(0xffff0000UL)) == PP_HTONL(0xa9fe0000UL))
|
||||
|
||||
#define ip_addr_debug_print(debug, ipaddr) \
|
||||
LWIP_DEBUGF(debug, ("%"U16_F".%"U16_F".%"U16_F".%"U16_F, \
|
||||
ipaddr != NULL ? \
|
||||
(u16_t)(ntohl((ipaddr)->addr) >> 24) & 0xff : 0, \
|
||||
ipaddr != NULL ? \
|
||||
(u16_t)(ntohl((ipaddr)->addr) >> 16) & 0xff : 0, \
|
||||
ipaddr != NULL ? \
|
||||
(u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff : 0, \
|
||||
ipaddr != NULL ? \
|
||||
(u16_t)ntohl((ipaddr)->addr) & 0xff : 0))
|
||||
LWIP_DEBUGF(debug, ("%"U16_F".%"U16_F".%"U16_F".%"U16_F, \
|
||||
ipaddr != NULL ? ip4_addr1_16(ipaddr) : 0, \
|
||||
ipaddr != NULL ? ip4_addr2_16(ipaddr) : 0, \
|
||||
ipaddr != NULL ? ip4_addr3_16(ipaddr) : 0, \
|
||||
ipaddr != NULL ? ip4_addr4_16(ipaddr) : 0))
|
||||
|
||||
/* Get one byte from the 4-byte address */
|
||||
#define ip4_addr1(ipaddr) (((u8_t*)(ipaddr))[0])
|
||||
#define ip4_addr2(ipaddr) (((u8_t*)(ipaddr))[1])
|
||||
#define ip4_addr3(ipaddr) (((u8_t*)(ipaddr))[2])
|
||||
#define ip4_addr4(ipaddr) (((u8_t*)(ipaddr))[3])
|
||||
/* These are cast to u16_t, with the intent that they are often arguments
|
||||
* to printf using the U16_F format from cc.h. */
|
||||
#define ip4_addr1(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 24) & 0xff)
|
||||
#define ip4_addr2(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 16) & 0xff)
|
||||
#define ip4_addr3(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff)
|
||||
#define ip4_addr4(ipaddr) ((u16_t)(ntohl((ipaddr)->addr)) & 0xff)
|
||||
#define ip4_addr1_16(ipaddr) ((u16_t)ip4_addr1(ipaddr))
|
||||
#define ip4_addr2_16(ipaddr) ((u16_t)ip4_addr2(ipaddr))
|
||||
#define ip4_addr3_16(ipaddr) ((u16_t)ip4_addr3(ipaddr))
|
||||
#define ip4_addr4_16(ipaddr) ((u16_t)ip4_addr4(ipaddr))
|
||||
|
||||
/**
|
||||
* Same as inet_ntoa() but takes a struct ip_addr*
|
||||
*/
|
||||
#define ip_ntoa(addr) ((addr != NULL) ? inet_ntoa(*((struct in_addr*)(addr))) : "NULL")
|
||||
/** For backwards compatibility */
|
||||
#define ip_ntoa(ipaddr) ipaddr_ntoa(ipaddr)
|
||||
|
||||
u32_t ipaddr_addr(const char *cp);
|
||||
int ipaddr_aton(const char *cp, ip_addr_t *addr);
|
||||
/** returns ptr to static buffer; not reentrant! */
|
||||
char *ipaddr_ntoa(const ip_addr_t *addr);
|
||||
char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -66,7 +66,19 @@ struct pbuf * ip_reass(struct pbuf *p);
|
||||
#endif /* IP_REASSEMBLY */
|
||||
|
||||
#if IP_FRAG
|
||||
err_t ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest);
|
||||
#if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF
|
||||
/** A custom pbuf that holds a reference to another pbuf, which is freed
|
||||
* when this custom pbuf is freed. This is used to create a custom PBUF_REF
|
||||
* that points into the original pbuf. */
|
||||
struct pbuf_custom_ref {
|
||||
/** 'base class' */
|
||||
struct pbuf_custom pc;
|
||||
/** pointer to the original pbuf that is referenced */
|
||||
struct pbuf *original;
|
||||
};
|
||||
#endif /* !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */
|
||||
|
||||
err_t ip_frag(struct pbuf *p, struct netif *netif, ip_addr_t *dest);
|
||||
#endif /* IP_FRAG */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -51,16 +51,35 @@ extern "C" {
|
||||
* the same byte order as in the corresponding pcb.
|
||||
*/
|
||||
|
||||
/* Flags for netconn_write */
|
||||
#define NETCONN_NOFLAG 0x00
|
||||
#define NETCONN_NOCOPY 0x00 /* Only for source code compatibility */
|
||||
#define NETCONN_COPY 0x01
|
||||
#define NETCONN_MORE 0x02
|
||||
/* Flags for netconn_write (u8_t) */
|
||||
#define NETCONN_NOFLAG 0x00
|
||||
#define NETCONN_NOCOPY 0x00 /* Only for source code compatibility */
|
||||
#define NETCONN_COPY 0x01
|
||||
#define NETCONN_MORE 0x02
|
||||
#define NETCONN_DONTBLOCK 0x04
|
||||
|
||||
/* Flags for struct netconn.flags (u8_t) */
|
||||
/** TCP: when data passed to netconn_write doesn't fit into the send buffer,
|
||||
this temporarily stores whether to wake up the original application task
|
||||
if data couldn't be sent in the first try. */
|
||||
#define NETCONN_FLAG_WRITE_DELAYED 0x01
|
||||
/** Should this netconn avoid blocking? */
|
||||
#define NETCONN_FLAG_NON_BLOCKING 0x02
|
||||
/** Was the last connect action a non-blocking one? */
|
||||
#define NETCONN_FLAG_IN_NONBLOCKING_CONNECT 0x04
|
||||
/** If this is set, a TCP netconn must call netconn_recved() to update
|
||||
the TCP receive window (done automatically if not set). */
|
||||
#define NETCONN_FLAG_NO_AUTO_RECVED 0x08
|
||||
/** If a nonblocking write has been rejected before, poll_tcp needs to
|
||||
check if the netconn is writable again */
|
||||
#define NETCONN_FLAG_CHECK_WRITESPACE 0x10
|
||||
|
||||
|
||||
/* Helpers to process several netconn_types by the same code */
|
||||
#define NETCONNTYPE_GROUP(t) (t&0xF0)
|
||||
#define NETCONNTYPE_DATAGRAM(t) (t&0xE0)
|
||||
|
||||
/** Protocol family and type of the netconn */
|
||||
enum netconn_type {
|
||||
NETCONN_INVALID = 0,
|
||||
/* NETCONN_TCP Group */
|
||||
@@ -73,6 +92,8 @@ enum netconn_type {
|
||||
NETCONN_RAW = 0x40
|
||||
};
|
||||
|
||||
/** Current state of the netconn. Non-TCP netconns are always
|
||||
* in state NETCONN_NONE! */
|
||||
enum netconn_state {
|
||||
NETCONN_NONE,
|
||||
NETCONN_WRITE,
|
||||
@@ -81,14 +102,17 @@ enum netconn_state {
|
||||
NETCONN_CLOSE
|
||||
};
|
||||
|
||||
/** Use to inform the callback function about changes */
|
||||
enum netconn_evt {
|
||||
NETCONN_EVT_RCVPLUS,
|
||||
NETCONN_EVT_RCVMINUS,
|
||||
NETCONN_EVT_SENDPLUS,
|
||||
NETCONN_EVT_SENDMINUS
|
||||
NETCONN_EVT_SENDMINUS,
|
||||
NETCONN_EVT_ERROR
|
||||
};
|
||||
|
||||
#if LWIP_IGMP
|
||||
/** Used for netconn_join_leave_group() */
|
||||
enum netconn_igmp {
|
||||
NETCONN_JOIN,
|
||||
NETCONN_LEAVE
|
||||
@@ -101,6 +125,7 @@ struct tcp_pcb;
|
||||
struct udp_pcb;
|
||||
struct raw_pcb;
|
||||
struct netconn;
|
||||
struct api_msg_msg;
|
||||
|
||||
/** A callback prototype to inform about events for a netconn */
|
||||
typedef void (* netconn_callback)(struct netconn *, enum netconn_evt, u16_t len);
|
||||
@@ -119,99 +144,149 @@ struct netconn {
|
||||
struct raw_pcb *raw;
|
||||
} pcb;
|
||||
/** the last error this netconn had */
|
||||
err_t err;
|
||||
err_t last_err;
|
||||
/** sem that is used to synchroneously execute functions in the core context */
|
||||
sys_sem_t op_completed;
|
||||
/** mbox where received packets are stored until they are fetched
|
||||
by the netconn application thread (can grow quite big) */
|
||||
sys_mbox_t recvmbox;
|
||||
#if LWIP_TCP
|
||||
/** mbox where new connections are stored until processed
|
||||
by the application thread */
|
||||
sys_mbox_t acceptmbox;
|
||||
#endif /* LWIP_TCP */
|
||||
/** only used for socket layer */
|
||||
#if LWIP_SOCKET
|
||||
int socket;
|
||||
#endif /* LWIP_SOCKET */
|
||||
#if LWIP_SO_SNDTIMEO
|
||||
/** timeout to wait for sending data (which means enqueueing data for sending
|
||||
in internal buffers) */
|
||||
s32_t send_timeout;
|
||||
#endif /* LWIP_SO_RCVTIMEO */
|
||||
#if LWIP_SO_RCVTIMEO
|
||||
/** timeout to wait for new data to be received
|
||||
(or connections to arrive for listening netconns) */
|
||||
int recv_timeout;
|
||||
#endif /* LWIP_SO_RCVTIMEO */
|
||||
#if LWIP_SO_RCVBUF
|
||||
/** maximum amount of bytes queued in recvmbox */
|
||||
/** maximum amount of bytes queued in recvmbox
|
||||
not used for TCP: adjust TCP_WND instead! */
|
||||
int recv_bufsize;
|
||||
#endif /* LWIP_SO_RCVBUF */
|
||||
/** number of bytes currently in recvmbox to be received,
|
||||
tested against recv_bufsize to limit bytes on recvmbox
|
||||
for UDP and RAW, used for FIONREAD */
|
||||
s16_t recv_avail;
|
||||
#endif /* LWIP_SO_RCVBUF */
|
||||
/** flags holding more netconn-internal state, see NETCONN_FLAG_* defines */
|
||||
u8_t flags;
|
||||
#if LWIP_TCP
|
||||
/** TCP: when data passed to netconn_write doesn't fit into the send buffer,
|
||||
this temporarily stores the message. */
|
||||
struct api_msg_msg *write_msg;
|
||||
/** TCP: when data passed to netconn_write doesn't fit into the send buffer,
|
||||
this temporarily stores how much is already sent. */
|
||||
size_t write_offset;
|
||||
#if LWIP_TCPIP_CORE_LOCKING
|
||||
/** TCP: when data passed to netconn_write doesn't fit into the send buffer,
|
||||
this temporarily stores whether to wake up the original application task
|
||||
if data couldn't be sent in the first try. */
|
||||
u8_t write_delayed;
|
||||
#endif /* LWIP_TCPIP_CORE_LOCKING */
|
||||
this temporarily stores the message.
|
||||
Also used during connect and close. */
|
||||
struct api_msg_msg *current_msg;
|
||||
#endif /* LWIP_TCP */
|
||||
/** A callback function that is informed about events for this netconn */
|
||||
netconn_callback callback;
|
||||
};
|
||||
|
||||
/* Register an Network connection event */
|
||||
/** Register an Network connection event */
|
||||
#define API_EVENT(c,e,l) if (c->callback) { \
|
||||
(*c->callback)(c, e, l); \
|
||||
}
|
||||
|
||||
/** Set conn->last_err to err but don't overwrite fatal errors */
|
||||
#define NETCONN_SET_SAFE_ERR(conn, err) do { \
|
||||
SYS_ARCH_DECL_PROTECT(lev); \
|
||||
SYS_ARCH_PROTECT(lev); \
|
||||
if (!ERR_IS_FATAL((conn)->last_err)) { \
|
||||
(conn)->last_err = err; \
|
||||
} \
|
||||
SYS_ARCH_UNPROTECT(lev); \
|
||||
} while(0);
|
||||
|
||||
/* Network connection functions: */
|
||||
#define netconn_new(t) netconn_new_with_proto_and_callback(t, 0, NULL)
|
||||
#define netconn_new_with_callback(t, c) netconn_new_with_proto_and_callback(t, 0, c)
|
||||
struct
|
||||
netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto,
|
||||
netconn_callback callback);
|
||||
err_t netconn_delete (struct netconn *conn);
|
||||
netconn_callback callback);
|
||||
err_t netconn_delete(struct netconn *conn);
|
||||
/** Get the type of a netconn (as enum netconn_type). */
|
||||
#define netconn_type(conn) (conn->type)
|
||||
|
||||
err_t netconn_getaddr (struct netconn *conn,
|
||||
struct ip_addr *addr,
|
||||
u16_t *port,
|
||||
u8_t local);
|
||||
err_t netconn_getaddr(struct netconn *conn, ip_addr_t *addr,
|
||||
u16_t *port, u8_t local);
|
||||
#define netconn_peer(c,i,p) netconn_getaddr(c,i,p,0)
|
||||
#define netconn_addr(c,i,p) netconn_getaddr(c,i,p,1)
|
||||
|
||||
err_t netconn_bind (struct netconn *conn,
|
||||
struct ip_addr *addr,
|
||||
u16_t port);
|
||||
err_t netconn_connect (struct netconn *conn,
|
||||
struct ip_addr *addr,
|
||||
u16_t port);
|
||||
err_t netconn_disconnect (struct netconn *conn);
|
||||
err_t netconn_listen_with_backlog(struct netconn *conn, u8_t backlog);
|
||||
err_t netconn_bind(struct netconn *conn, ip_addr_t *addr, u16_t port);
|
||||
err_t netconn_connect(struct netconn *conn, ip_addr_t *addr, u16_t port);
|
||||
err_t netconn_disconnect (struct netconn *conn);
|
||||
err_t netconn_listen_with_backlog(struct netconn *conn, u8_t backlog);
|
||||
#define netconn_listen(conn) netconn_listen_with_backlog(conn, TCP_DEFAULT_LISTEN_BACKLOG)
|
||||
struct netconn * netconn_accept (struct netconn *conn);
|
||||
struct netbuf * netconn_recv (struct netconn *conn);
|
||||
err_t netconn_sendto (struct netconn *conn,
|
||||
struct netbuf *buf, struct ip_addr *addr, u16_t port);
|
||||
err_t netconn_send (struct netconn *conn,
|
||||
struct netbuf *buf);
|
||||
err_t netconn_write (struct netconn *conn,
|
||||
const void *dataptr, size_t size,
|
||||
u8_t apiflags);
|
||||
err_t netconn_close (struct netconn *conn);
|
||||
err_t netconn_accept(struct netconn *conn, struct netconn **new_conn);
|
||||
err_t netconn_recv(struct netconn *conn, struct netbuf **new_buf);
|
||||
err_t netconn_recv_tcp_pbuf(struct netconn *conn, struct pbuf **new_buf);
|
||||
void netconn_recved(struct netconn *conn, u32_t length);
|
||||
err_t netconn_sendto(struct netconn *conn, struct netbuf *buf,
|
||||
ip_addr_t *addr, u16_t port);
|
||||
err_t netconn_send(struct netconn *conn, struct netbuf *buf);
|
||||
err_t netconn_write_partly(struct netconn *conn, const void *dataptr, size_t size,
|
||||
u8_t apiflags, size_t *bytes_written);
|
||||
#define netconn_write(conn, dataptr, size, apiflags) \
|
||||
netconn_write_partly(conn, dataptr, size, apiflags, NULL)
|
||||
err_t netconn_close(struct netconn *conn);
|
||||
err_t netconn_shutdown(struct netconn *conn, u8_t shut_rx, u8_t shut_tx);
|
||||
|
||||
#if LWIP_IGMP
|
||||
err_t netconn_join_leave_group (struct netconn *conn,
|
||||
struct ip_addr *multiaddr,
|
||||
struct ip_addr *interface,
|
||||
enum netconn_igmp join_or_leave);
|
||||
err_t netconn_join_leave_group(struct netconn *conn, ip_addr_t *multiaddr,
|
||||
ip_addr_t *netif_addr, enum netconn_igmp join_or_leave);
|
||||
#endif /* LWIP_IGMP */
|
||||
#if LWIP_DNS
|
||||
err_t netconn_gethostbyname(const char *name, struct ip_addr *addr);
|
||||
err_t netconn_gethostbyname(const char *name, ip_addr_t *addr);
|
||||
#endif /* LWIP_DNS */
|
||||
|
||||
#define netconn_err(conn) ((conn)->err)
|
||||
#define netconn_recv_bufsize(conn) ((conn)->recv_bufsize)
|
||||
#define netconn_err(conn) ((conn)->last_err)
|
||||
#define netconn_recv_bufsize(conn) ((conn)->recv_bufsize)
|
||||
|
||||
/** Set the blocking status of netconn calls (@todo: write/send is missing) */
|
||||
#define netconn_set_nonblocking(conn, val) do { if(val) { \
|
||||
(conn)->flags |= NETCONN_FLAG_NON_BLOCKING; \
|
||||
} else { \
|
||||
(conn)->flags &= ~ NETCONN_FLAG_NON_BLOCKING; }} while(0)
|
||||
/** Get the blocking status of netconn calls (@todo: write/send is missing) */
|
||||
#define netconn_is_nonblocking(conn) (((conn)->flags & NETCONN_FLAG_NON_BLOCKING) != 0)
|
||||
|
||||
/** TCP: Set the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */
|
||||
#define netconn_set_noautorecved(conn, val) do { if(val) { \
|
||||
(conn)->flags |= NETCONN_FLAG_NO_AUTO_RECVED; \
|
||||
} else { \
|
||||
(conn)->flags &= ~ NETCONN_FLAG_NO_AUTO_RECVED; }} while(0)
|
||||
/** TCP: Get the no-auto-recved status of netconn calls (see NETCONN_FLAG_NO_AUTO_RECVED) */
|
||||
#define netconn_get_noautorecved(conn) (((conn)->flags & NETCONN_FLAG_NO_AUTO_RECVED) != 0)
|
||||
|
||||
#if LWIP_SO_SNDTIMEO
|
||||
/** Set the send timeout in milliseconds */
|
||||
#define netconn_set_sendtimeout(conn, timeout) ((conn)->send_timeout = (timeout))
|
||||
/** Get the send timeout in milliseconds */
|
||||
#define netconn_get_sendtimeout(conn) ((conn)->send_timeout)
|
||||
#endif /* LWIP_SO_SNDTIMEO */
|
||||
#if LWIP_SO_RCVTIMEO
|
||||
/** Set the receive timeout in milliseconds */
|
||||
#define netconn_set_recvtimeout(conn, timeout) ((conn)->recv_timeout = (timeout))
|
||||
/** Get the receive timeout in milliseconds */
|
||||
#define netconn_get_recvtimeout(conn) ((conn)->recv_timeout)
|
||||
#endif /* LWIP_SO_RCVTIMEO */
|
||||
#if LWIP_SO_RCVBUF
|
||||
/** Set the receive buffer in bytes */
|
||||
#define netconn_set_recvbufsize(conn, recvbufsize) ((conn)->recv_bufsize = (recvbufsize))
|
||||
/** Get the receive buffer in bytes */
|
||||
#define netconn_get_recvbufsize(conn) ((conn)->recv_bufsize)
|
||||
#endif /* LWIP_SO_RCVBUF*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -48,6 +48,11 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* For the netconn API, these values are use as a bitmask! */
|
||||
#define NETCONN_SHUT_RD 1
|
||||
#define NETCONN_SHUT_WR 2
|
||||
#define NETCONN_SHUT_RDWR (NETCONN_SHUT_RD | NETCONN_SHUT_WR)
|
||||
|
||||
/* IP addresses and port numbers are expected to be in
|
||||
* the same byte order as in the corresponding pcb.
|
||||
*/
|
||||
@@ -58,6 +63,8 @@ struct api_msg_msg {
|
||||
/** The netconn which to process - always needed: it includes the semaphore
|
||||
which is used to block the application thread until the function finished. */
|
||||
struct netconn *conn;
|
||||
/** The return value of the function executed in tcpip_thread. */
|
||||
err_t err;
|
||||
/** Depending on the executed function, one of these union members is used */
|
||||
union {
|
||||
/** used for do_send */
|
||||
@@ -68,12 +75,12 @@ struct api_msg_msg {
|
||||
} n;
|
||||
/** used for do_bind and do_connect */
|
||||
struct {
|
||||
struct ip_addr *ipaddr;
|
||||
ip_addr_t *ipaddr;
|
||||
u16_t port;
|
||||
} bc;
|
||||
/** used for do_getaddr */
|
||||
struct {
|
||||
struct ip_addr *ipaddr;
|
||||
ip_addr_t *ipaddr;
|
||||
u16_t *port;
|
||||
u8_t local;
|
||||
} ad;
|
||||
@@ -82,16 +89,23 @@ struct api_msg_msg {
|
||||
const void *dataptr;
|
||||
size_t len;
|
||||
u8_t apiflags;
|
||||
#if LWIP_SO_SNDTIMEO
|
||||
u32_t time_started;
|
||||
#endif /* LWIP_SO_SNDTIMEO */
|
||||
} w;
|
||||
/** used for do_recv */
|
||||
struct {
|
||||
u16_t len;
|
||||
u32_t len;
|
||||
} r;
|
||||
/** used for do_close (/shutdown) */
|
||||
struct {
|
||||
u8_t shut;
|
||||
} sd;
|
||||
#if LWIP_IGMP
|
||||
/** used for do_join_leave_group */
|
||||
struct {
|
||||
struct ip_addr *multiaddr;
|
||||
struct ip_addr *interface;
|
||||
ip_addr_t *multiaddr;
|
||||
ip_addr_t *netif_addr;
|
||||
enum netconn_igmp join_or_leave;
|
||||
} jl;
|
||||
#endif /* LWIP_IGMP */
|
||||
@@ -122,10 +136,10 @@ struct dns_api_msg {
|
||||
/** Hostname to query or dotted IP address string */
|
||||
const char *name;
|
||||
/** Rhe resolved address is stored here */
|
||||
struct ip_addr *addr;
|
||||
ip_addr_t *addr;
|
||||
/** This semaphore is posted when the name is resolved, the application thread
|
||||
should wait on it. */
|
||||
sys_sem_t sem;
|
||||
sys_sem_t *sem;
|
||||
/** Errors are given back here */
|
||||
err_t *err;
|
||||
};
|
||||
@@ -142,6 +156,7 @@ void do_recv ( struct api_msg_msg *msg);
|
||||
void do_write ( struct api_msg_msg *msg);
|
||||
void do_getaddr ( struct api_msg_msg *msg);
|
||||
void do_close ( struct api_msg_msg *msg);
|
||||
void do_shutdown ( struct api_msg_msg *msg);
|
||||
#if LWIP_IGMP
|
||||
void do_join_leave_group( struct api_msg_msg *msg);
|
||||
#endif /* LWIP_IGMP */
|
||||
|
||||
@@ -46,6 +46,11 @@
|
||||
#ifndef SZT_F
|
||||
#define SZT_F U32_F
|
||||
#endif /* SZT_F */
|
||||
/** Temporary upgrade helper: define format string for u8_t as hex if not
|
||||
defined in cc.h */
|
||||
#ifndef X8_F
|
||||
#define X8_F "02x"
|
||||
#endif /* X8_F */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -71,154 +76,133 @@ extern "C" {
|
||||
|
||||
#ifdef LWIP_PROVIDE_ERRNO
|
||||
|
||||
#define EPERM 1 /* Operation not permitted */
|
||||
#define ENOENT 2 /* No such file or directory */
|
||||
#define ESRCH 3 /* No such process */
|
||||
#define EINTR 4 /* Interrupted system call */
|
||||
#define EIO 5 /* I/O error */
|
||||
#define ENXIO 6 /* No such device or address */
|
||||
#define E2BIG 7 /* Arg list too long */
|
||||
#define ENOEXEC 8 /* Exec format error */
|
||||
#define EBADF 9 /* Bad file number */
|
||||
#define ECHILD 10 /* No child processes */
|
||||
#define EAGAIN 11 /* Try again */
|
||||
#define ENOMEM 12 /* Out of memory */
|
||||
#define EACCES 13 /* Permission denied */
|
||||
#define EFAULT 14 /* Bad address */
|
||||
#define ENOTBLK 15 /* Block device required */
|
||||
#define EBUSY 16 /* Device or resource busy */
|
||||
#define EEXIST 17 /* File exists */
|
||||
#define EXDEV 18 /* Cross-device link */
|
||||
#define ENODEV 19 /* No such device */
|
||||
#define ENOTDIR 20 /* Not a directory */
|
||||
#define EISDIR 21 /* Is a directory */
|
||||
#define EINVAL 22 /* Invalid argument */
|
||||
#define ENFILE 23 /* File table overflow */
|
||||
#define EMFILE 24 /* Too many open files */
|
||||
#define ENOTTY 25 /* Not a typewriter */
|
||||
#define ETXTBSY 26 /* Text file busy */
|
||||
#define EFBIG 27 /* File too large */
|
||||
#define ENOSPC 28 /* No space left on device */
|
||||
#define ESPIPE 29 /* Illegal seek */
|
||||
#define EROFS 30 /* Read-only file system */
|
||||
#define EMLINK 31 /* Too many links */
|
||||
#define EPIPE 32 /* Broken pipe */
|
||||
#define EDOM 33 /* Math argument out of domain of func */
|
||||
#define ERANGE 34 /* Math result not representable */
|
||||
#define EDEADLK 35 /* Resource deadlock would occur */
|
||||
#define ENAMETOOLONG 36 /* File name too long */
|
||||
#define ENOLCK 37 /* No record locks available */
|
||||
#define ENOSYS 38 /* Function not implemented */
|
||||
#define ENOTEMPTY 39 /* Directory not empty */
|
||||
#define ELOOP 40 /* Too many symbolic links encountered */
|
||||
#define EPERM 1 /* Operation not permitted */
|
||||
#define ENOENT 2 /* No such file or directory */
|
||||
#define ESRCH 3 /* No such process */
|
||||
#define EINTR 4 /* Interrupted system call */
|
||||
#define EIO 5 /* I/O error */
|
||||
#define ENXIO 6 /* No such device or address */
|
||||
#define E2BIG 7 /* Arg list too long */
|
||||
#define ENOEXEC 8 /* Exec format error */
|
||||
#define EBADF 9 /* Bad file number */
|
||||
#define ECHILD 10 /* No child processes */
|
||||
#define EAGAIN 11 /* Try again */
|
||||
#define ENOMEM 12 /* Out of memory */
|
||||
#define EACCES 13 /* Permission denied */
|
||||
#define EFAULT 14 /* Bad address */
|
||||
#define ENOTBLK 15 /* Block device required */
|
||||
#define EBUSY 16 /* Device or resource busy */
|
||||
#define EEXIST 17 /* File exists */
|
||||
#define EXDEV 18 /* Cross-device link */
|
||||
#define ENODEV 19 /* No such device */
|
||||
#define ENOTDIR 20 /* Not a directory */
|
||||
#define EISDIR 21 /* Is a directory */
|
||||
#define EINVAL 22 /* Invalid argument */
|
||||
#define ENFILE 23 /* File table overflow */
|
||||
#define EMFILE 24 /* Too many open files */
|
||||
#define ENOTTY 25 /* Not a typewriter */
|
||||
#define ETXTBSY 26 /* Text file busy */
|
||||
#define EFBIG 27 /* File too large */
|
||||
#define ENOSPC 28 /* No space left on device */
|
||||
#define ESPIPE 29 /* Illegal seek */
|
||||
#define EROFS 30 /* Read-only file system */
|
||||
#define EMLINK 31 /* Too many links */
|
||||
#define EPIPE 32 /* Broken pipe */
|
||||
#define EDOM 33 /* Math argument out of domain of func */
|
||||
#define ERANGE 34 /* Math result not representable */
|
||||
#define EDEADLK 35 /* Resource deadlock would occur */
|
||||
#define ENAMETOOLONG 36 /* File name too long */
|
||||
#define ENOLCK 37 /* No record locks available */
|
||||
#define ENOSYS 38 /* Function not implemented */
|
||||
#define ENOTEMPTY 39 /* Directory not empty */
|
||||
#define ELOOP 40 /* Too many symbolic links encountered */
|
||||
#define EWOULDBLOCK EAGAIN /* Operation would block */
|
||||
#define ENOMSG 42 /* No message of desired type */
|
||||
#define EIDRM 43 /* Identifier removed */
|
||||
#define ECHRNG 44 /* Channel number out of range */
|
||||
#define EL2NSYNC 45 /* Level 2 not synchronized */
|
||||
#define EL3HLT 46 /* Level 3 halted */
|
||||
#define EL3RST 47 /* Level 3 reset */
|
||||
#define ELNRNG 48 /* Link number out of range */
|
||||
#define EUNATCH 49 /* Protocol driver not attached */
|
||||
#define ENOCSI 50 /* No CSI structure available */
|
||||
#define EL2HLT 51 /* Level 2 halted */
|
||||
#define EBADE 52 /* Invalid exchange */
|
||||
#define EBADR 53 /* Invalid request descriptor */
|
||||
#define EXFULL 54 /* Exchange full */
|
||||
#define ENOANO 55 /* No anode */
|
||||
#define EBADRQC 56 /* Invalid request code */
|
||||
#define EBADSLT 57 /* Invalid slot */
|
||||
#define ENOMSG 42 /* No message of desired type */
|
||||
#define EIDRM 43 /* Identifier removed */
|
||||
#define ECHRNG 44 /* Channel number out of range */
|
||||
#define EL2NSYNC 45 /* Level 2 not synchronized */
|
||||
#define EL3HLT 46 /* Level 3 halted */
|
||||
#define EL3RST 47 /* Level 3 reset */
|
||||
#define ELNRNG 48 /* Link number out of range */
|
||||
#define EUNATCH 49 /* Protocol driver not attached */
|
||||
#define ENOCSI 50 /* No CSI structure available */
|
||||
#define EL2HLT 51 /* Level 2 halted */
|
||||
#define EBADE 52 /* Invalid exchange */
|
||||
#define EBADR 53 /* Invalid request descriptor */
|
||||
#define EXFULL 54 /* Exchange full */
|
||||
#define ENOANO 55 /* No anode */
|
||||
#define EBADRQC 56 /* Invalid request code */
|
||||
#define EBADSLT 57 /* Invalid slot */
|
||||
|
||||
#define EDEADLOCK EDEADLK
|
||||
#define EDEADLOCK EDEADLK
|
||||
|
||||
#define EBFONT 59 /* Bad font file format */
|
||||
#define ENOSTR 60 /* Device not a stream */
|
||||
#define ENODATA 61 /* No data available */
|
||||
#define ETIME 62 /* Timer expired */
|
||||
#define ENOSR 63 /* Out of streams resources */
|
||||
#define ENONET 64 /* Machine is not on the network */
|
||||
#define ENOPKG 65 /* Package not installed */
|
||||
#define EREMOTE 66 /* Object is remote */
|
||||
#define ENOLINK 67 /* Link has been severed */
|
||||
#define EADV 68 /* Advertise error */
|
||||
#define ESRMNT 69 /* Srmount error */
|
||||
#define ECOMM 70 /* Communication error on send */
|
||||
#define EPROTO 71 /* Protocol error */
|
||||
#define EMULTIHOP 72 /* Multihop attempted */
|
||||
#define EDOTDOT 73 /* RFS specific error */
|
||||
#define EBADMSG 74 /* Not a data message */
|
||||
#define EOVERFLOW 75 /* Value too large for defined data type */
|
||||
#define ENOTUNIQ 76 /* Name not unique on network */
|
||||
#define EBADFD 77 /* File descriptor in bad state */
|
||||
#define EREMCHG 78 /* Remote address changed */
|
||||
#define ELIBACC 79 /* Can not access a needed shared library */
|
||||
#define ELIBBAD 80 /* Accessing a corrupted shared library */
|
||||
#define ELIBSCN 81 /* .lib section in a.out corrupted */
|
||||
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
|
||||
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
|
||||
#define EILSEQ 84 /* Illegal byte sequence */
|
||||
#define ERESTART 85 /* Interrupted system call should be restarted */
|
||||
#define ESTRPIPE 86 /* Streams pipe error */
|
||||
#define EUSERS 87 /* Too many users */
|
||||
#define ENOTSOCK 88 /* Socket operation on non-socket */
|
||||
#define EDESTADDRREQ 89 /* Destination address required */
|
||||
#define EMSGSIZE 90 /* Message too long */
|
||||
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
|
||||
#define EBFONT 59 /* Bad font file format */
|
||||
#define ENOSTR 60 /* Device not a stream */
|
||||
#define ENODATA 61 /* No data available */
|
||||
#define ETIME 62 /* Timer expired */
|
||||
#define ENOSR 63 /* Out of streams resources */
|
||||
#define ENONET 64 /* Machine is not on the network */
|
||||
#define ENOPKG 65 /* Package not installed */
|
||||
#define EREMOTE 66 /* Object is remote */
|
||||
#define ENOLINK 67 /* Link has been severed */
|
||||
#define EADV 68 /* Advertise error */
|
||||
#define ESRMNT 69 /* Srmount error */
|
||||
#define ECOMM 70 /* Communication error on send */
|
||||
#define EPROTO 71 /* Protocol error */
|
||||
#define EMULTIHOP 72 /* Multihop attempted */
|
||||
#define EDOTDOT 73 /* RFS specific error */
|
||||
#define EBADMSG 74 /* Not a data message */
|
||||
#define EOVERFLOW 75 /* Value too large for defined data type */
|
||||
#define ENOTUNIQ 76 /* Name not unique on network */
|
||||
#define EBADFD 77 /* File descriptor in bad state */
|
||||
#define EREMCHG 78 /* Remote address changed */
|
||||
#define ELIBACC 79 /* Can not access a needed shared library */
|
||||
#define ELIBBAD 80 /* Accessing a corrupted shared library */
|
||||
#define ELIBSCN 81 /* .lib section in a.out corrupted */
|
||||
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
|
||||
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
|
||||
#define EILSEQ 84 /* Illegal byte sequence */
|
||||
#define ERESTART 85 /* Interrupted system call should be restarted */
|
||||
#define ESTRPIPE 86 /* Streams pipe error */
|
||||
#define EUSERS 87 /* Too many users */
|
||||
#define ENOTSOCK 88 /* Socket operation on non-socket */
|
||||
#define EDESTADDRREQ 89 /* Destination address required */
|
||||
#define EMSGSIZE 90 /* Message too long */
|
||||
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
|
||||
#define ENOPROTOOPT 92 /* Protocol not available */
|
||||
#define EPROTONOSUPPORT 93 /* Protocol not supported */
|
||||
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
|
||||
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
|
||||
#define EPFNOSUPPORT 96 /* Protocol family not supported */
|
||||
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
|
||||
#define EADDRINUSE 98 /* Address already in use */
|
||||
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
|
||||
#define ENETDOWN 100 /* Network is down */
|
||||
#define ENETUNREACH 101 /* Network is unreachable */
|
||||
#define ENETRESET 102 /* Network dropped connection because of reset */
|
||||
#define ECONNABORTED 103 /* Software caused connection abort */
|
||||
#define ECONNRESET 104 /* Connection reset by peer */
|
||||
#define ENOBUFS 105 /* No buffer space available */
|
||||
#define EISCONN 106 /* Transport endpoint is already connected */
|
||||
#define ENOTCONN 107 /* Transport endpoint is not connected */
|
||||
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
|
||||
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
|
||||
#define ETIMEDOUT 110 /* Connection timed out */
|
||||
#define ECONNREFUSED 111 /* Connection refused */
|
||||
#define EHOSTDOWN 112 /* Host is down */
|
||||
#define EHOSTUNREACH 113 /* No route to host */
|
||||
#define EALREADY 114 /* Operation already in progress */
|
||||
#define EINPROGRESS 115 /* Operation now in progress */
|
||||
#define ESTALE 116 /* Stale NFS file handle */
|
||||
#define EUCLEAN 117 /* Structure needs cleaning */
|
||||
#define ENOTNAM 118 /* Not a XENIX named type file */
|
||||
#define ENAVAIL 119 /* No XENIX semaphores available */
|
||||
#define EISNAM 120 /* Is a named type file */
|
||||
#define EREMOTEIO 121 /* Remote I/O error */
|
||||
#define EDQUOT 122 /* Quota exceeded */
|
||||
#define EPROTONOSUPPORT 93 /* Protocol not supported */
|
||||
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
|
||||
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
|
||||
#define EPFNOSUPPORT 96 /* Protocol family not supported */
|
||||
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
|
||||
#define EADDRINUSE 98 /* Address already in use */
|
||||
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
|
||||
#define ENETDOWN 100 /* Network is down */
|
||||
#define ENETUNREACH 101 /* Network is unreachable */
|
||||
#define ENETRESET 102 /* Network dropped connection because of reset */
|
||||
#define ECONNABORTED 103 /* Software caused connection abort */
|
||||
#define ECONNRESET 104 /* Connection reset by peer */
|
||||
#define ENOBUFS 105 /* No buffer space available */
|
||||
#define EISCONN 106 /* Transport endpoint is already connected */
|
||||
#define ENOTCONN 107 /* Transport endpoint is not connected */
|
||||
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
|
||||
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
|
||||
#define ETIMEDOUT 110 /* Connection timed out */
|
||||
#define ECONNREFUSED 111 /* Connection refused */
|
||||
#define EHOSTDOWN 112 /* Host is down */
|
||||
#define EHOSTUNREACH 113 /* No route to host */
|
||||
#define EALREADY 114 /* Operation already in progress */
|
||||
#define EINPROGRESS 115 /* Operation now in progress */
|
||||
#define ESTALE 116 /* Stale NFS file handle */
|
||||
#define EUCLEAN 117 /* Structure needs cleaning */
|
||||
#define ENOTNAM 118 /* Not a XENIX named type file */
|
||||
#define ENAVAIL 119 /* No XENIX semaphores available */
|
||||
#define EISNAM 120 /* Is a named type file */
|
||||
#define EREMOTEIO 121 /* Remote I/O error */
|
||||
#define EDQUOT 122 /* Quota exceeded */
|
||||
|
||||
#define ENOMEDIUM 123 /* No medium found */
|
||||
#define EMEDIUMTYPE 124 /* Wrong medium type */
|
||||
|
||||
|
||||
#define ENSROK 0 /* DNS server returned answer with no data */
|
||||
#define ENSRNODATA 160 /* DNS server returned answer with no data */
|
||||
#define ENSRFORMERR 161 /* DNS server claims query was misformatted */
|
||||
#define ENSRSERVFAIL 162 /* DNS server returned general failure */
|
||||
#define ENSRNOTFOUND 163 /* Domain name not found */
|
||||
#define ENSRNOTIMP 164 /* DNS server does not implement requested operation */
|
||||
#define ENSRREFUSED 165 /* DNS server refused query */
|
||||
#define ENSRBADQUERY 166 /* Misformatted DNS query */
|
||||
#define ENSRBADNAME 167 /* Misformatted domain name */
|
||||
#define ENSRBADFAMILY 168 /* Unsupported address family */
|
||||
#define ENSRBADRESP 169 /* Misformatted DNS reply */
|
||||
#define ENSRCONNREFUSED 170 /* Could not contact DNS servers */
|
||||
#define ENSRTIMEOUT 171 /* Timeout while contacting DNS servers */
|
||||
#define ENSROF 172 /* End of file */
|
||||
#define ENSRFILE 173 /* Error reading file */
|
||||
#define ENSRNOMEM 174 /* Out of memory */
|
||||
#define ENSRDESTRUCTION 175 /* Application terminated lookup */
|
||||
#define ENSRQUERYDOMAINTOOLONG 176 /* Domain name is too long */
|
||||
#define ENSRCNAMELOOP 177 /* Domain name is too long */
|
||||
#define ENOMEDIUM 123 /* No medium found */
|
||||
#define EMEDIUMTYPE 124 /* Wrong medium type */
|
||||
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#define __LWIP_DEBUG_H__
|
||||
|
||||
#include "lwip/arch.h"
|
||||
#include "lwip/opt.h"
|
||||
|
||||
/** lower two bits indicate debug level
|
||||
* - 0 all
|
||||
|
||||
@@ -32,8 +32,13 @@
|
||||
#ifndef __LWIP_DEF_H__
|
||||
#define __LWIP_DEF_H__
|
||||
|
||||
/* this might define NULL already */
|
||||
/* arch.h might define NULL already */
|
||||
#include "lwip/arch.h"
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define LWIP_MAX(x , y) (((x) > (y)) ? (x) : (y))
|
||||
#define LWIP_MIN(x , y) (((x) < (y)) ? (x) : (y))
|
||||
@@ -42,6 +47,77 @@
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
/* Endianess-optimized shifting of two u8_t to create one u16_t */
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
#define LWIP_MAKE_U16(a, b) ((a << 8) | b)
|
||||
#else
|
||||
#define LWIP_MAKE_U16(a, b) ((b << 8) | a)
|
||||
#endif
|
||||
|
||||
#ifndef LWIP_PLATFORM_BYTESWAP
|
||||
#define LWIP_PLATFORM_BYTESWAP 0
|
||||
#endif
|
||||
|
||||
#ifndef LWIP_PREFIX_BYTEORDER_FUNCS
|
||||
/* workaround for naming collisions on some platforms */
|
||||
|
||||
#ifdef htons
|
||||
#undef htons
|
||||
#endif /* htons */
|
||||
#ifdef htonl
|
||||
#undef htonl
|
||||
#endif /* htonl */
|
||||
#ifdef ntohs
|
||||
#undef ntohs
|
||||
#endif /* ntohs */
|
||||
#ifdef ntohl
|
||||
#undef ntohl
|
||||
#endif /* ntohl */
|
||||
|
||||
#define htons(x) lwip_htons(x)
|
||||
#define ntohs(x) lwip_ntohs(x)
|
||||
#define htonl(x) lwip_htonl(x)
|
||||
#define ntohl(x) lwip_ntohl(x)
|
||||
#endif /* LWIP_PREFIX_BYTEORDER_FUNCS */
|
||||
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
#define lwip_htons(x) (x)
|
||||
#define lwip_ntohs(x) (x)
|
||||
#define lwip_htonl(x) (x)
|
||||
#define lwip_ntohl(x) (x)
|
||||
#define PP_HTONS(x) (x)
|
||||
#define PP_NTOHS(x) (x)
|
||||
#define PP_HTONL(x) (x)
|
||||
#define PP_NTOHL(x) (x)
|
||||
#else /* BYTE_ORDER != BIG_ENDIAN */
|
||||
#if LWIP_PLATFORM_BYTESWAP
|
||||
#define lwip_htons(x) LWIP_PLATFORM_HTONS(x)
|
||||
#define lwip_ntohs(x) LWIP_PLATFORM_HTONS(x)
|
||||
#define lwip_htonl(x) LWIP_PLATFORM_HTONL(x)
|
||||
#define lwip_ntohl(x) LWIP_PLATFORM_HTONL(x)
|
||||
#else /* LWIP_PLATFORM_BYTESWAP */
|
||||
u16_t lwip_htons(u16_t x);
|
||||
u16_t lwip_ntohs(u16_t x);
|
||||
u32_t lwip_htonl(u32_t x);
|
||||
u32_t lwip_ntohl(u32_t x);
|
||||
#endif /* LWIP_PLATFORM_BYTESWAP */
|
||||
|
||||
/* These macros should be calculated by the preprocessor and are used
|
||||
with compile-time constants only (so that there is no little-endian
|
||||
overhead at runtime). */
|
||||
#define PP_HTONS(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
|
||||
#define PP_NTOHS(x) PP_HTONS(x)
|
||||
#define PP_HTONL(x) ((((x) & 0xff) << 24) | \
|
||||
(((x) & 0xff00) << 8) | \
|
||||
(((x) & 0xff0000UL) >> 8) | \
|
||||
(((x) & 0xff000000UL) >> 24))
|
||||
#define PP_NTOHL(x) PP_HTONL(x)
|
||||
|
||||
#endif /* BYTE_ORDER == BIG_ENDIAN */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __LWIP_DEF_H__ */
|
||||
|
||||
|
||||
@@ -22,6 +22,10 @@ extern "C" {
|
||||
/** period (in milliseconds) of the application calling dhcp_fine_tmr() */
|
||||
#define DHCP_FINE_TIMER_MSECS 500
|
||||
|
||||
#define DHCP_CHADDR_LEN 16U
|
||||
#define DHCP_SNAME_LEN 64U
|
||||
#define DHCP_FILE_LEN 128U
|
||||
|
||||
struct dhcp
|
||||
{
|
||||
/** transaction identifier of last sent request */
|
||||
@@ -30,14 +34,14 @@ struct dhcp
|
||||
struct udp_pcb *pcb;
|
||||
/** incoming msg */
|
||||
struct dhcp_msg *msg_in;
|
||||
/** incoming msg options */
|
||||
void *options_in;
|
||||
/** ingoing msg options length */
|
||||
u16_t options_in_len;
|
||||
/** current DHCP state machine state */
|
||||
u8_t state;
|
||||
/** retries of current request */
|
||||
u8_t tries;
|
||||
#if LWIP_DHCP_AUTOIP_COOP
|
||||
u8_t autoip_coop_state;
|
||||
#endif
|
||||
u8_t subnet_mask_given;
|
||||
|
||||
struct pbuf *p_out; /* pbuf of outcoming msg */
|
||||
struct dhcp_msg *msg_out; /* outgoing msg */
|
||||
@@ -45,28 +49,20 @@ struct dhcp
|
||||
u16_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */
|
||||
u16_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */
|
||||
u16_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */
|
||||
struct ip_addr server_ip_addr; /* dhcp server address that offered this lease */
|
||||
struct ip_addr offered_ip_addr;
|
||||
struct ip_addr offered_sn_mask;
|
||||
struct ip_addr offered_gw_addr;
|
||||
struct ip_addr offered_bc_addr;
|
||||
#define DHCP_MAX_DNS 2
|
||||
u32_t dns_count; /* actual number of DNS servers obtained */
|
||||
struct ip_addr offered_dns_addr[DHCP_MAX_DNS]; /* DNS server addresses */
|
||||
ip_addr_t server_ip_addr; /* dhcp server address that offered this lease */
|
||||
ip_addr_t offered_ip_addr;
|
||||
ip_addr_t offered_sn_mask;
|
||||
ip_addr_t offered_gw_addr;
|
||||
|
||||
u32_t offered_t0_lease; /* lease period (in seconds) */
|
||||
u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */
|
||||
u32_t offered_t2_rebind; /* recommended rebind time (usually 66% of lease period) */
|
||||
#if LWIP_DHCP_AUTOIP_COOP
|
||||
u8_t autoip_coop_state;
|
||||
#endif
|
||||
/** Patch #1308
|
||||
* TODO: See dhcp.c "TODO"s
|
||||
*/
|
||||
#if 0
|
||||
struct ip_addr offered_si_addr;
|
||||
u8_t *boot_file_name;
|
||||
#endif
|
||||
/* @todo: LWIP_DHCP_BOOTP_FILE configuration option?
|
||||
integrate with possible TFTP-client for booting? */
|
||||
#if LWIP_DHCP_BOOTP_FILE
|
||||
ip_addr_t offered_si_addr;
|
||||
char boot_file_name[DHCP_FILE_LEN];
|
||||
#endif /* LWIP_DHCP_BOOTPFILE */
|
||||
};
|
||||
|
||||
/* MUST be compiled with "pack structs" or equivalent! */
|
||||
@@ -84,15 +80,12 @@ struct dhcp_msg
|
||||
PACK_STRUCT_FIELD(u32_t xid);
|
||||
PACK_STRUCT_FIELD(u16_t secs);
|
||||
PACK_STRUCT_FIELD(u16_t flags);
|
||||
PACK_STRUCT_FIELD(struct ip_addr ciaddr);
|
||||
PACK_STRUCT_FIELD(struct ip_addr yiaddr);
|
||||
PACK_STRUCT_FIELD(struct ip_addr siaddr);
|
||||
PACK_STRUCT_FIELD(struct ip_addr giaddr);
|
||||
#define DHCP_CHADDR_LEN 16U
|
||||
PACK_STRUCT_FIELD(ip_addr_p_t ciaddr);
|
||||
PACK_STRUCT_FIELD(ip_addr_p_t yiaddr);
|
||||
PACK_STRUCT_FIELD(ip_addr_p_t siaddr);
|
||||
PACK_STRUCT_FIELD(ip_addr_p_t giaddr);
|
||||
PACK_STRUCT_FIELD(u8_t chaddr[DHCP_CHADDR_LEN]);
|
||||
#define DHCP_SNAME_LEN 64U
|
||||
PACK_STRUCT_FIELD(u8_t sname[DHCP_SNAME_LEN]);
|
||||
#define DHCP_FILE_LEN 128U
|
||||
PACK_STRUCT_FIELD(u8_t file[DHCP_FILE_LEN]);
|
||||
PACK_STRUCT_FIELD(u32_t cookie);
|
||||
#define DHCP_MIN_OPTIONS_LEN 68U
|
||||
@@ -112,6 +105,10 @@ PACK_STRUCT_END
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp);
|
||||
/** Remove a struct dhcp previously set to the netif using dhcp_set_struct() */
|
||||
#define dhcp_remove_struct(netif) do { (netif)->dhcp = NULL; } while(0)
|
||||
void dhcp_cleanup(struct netif *netif);
|
||||
/** start DHCP configuration */
|
||||
err_t dhcp_start(struct netif *netif);
|
||||
/** enforce early lease renewal (not needed normally)*/
|
||||
@@ -127,7 +124,7 @@ void dhcp_network_changed(struct netif *netif);
|
||||
|
||||
/** if enabled, check whether the offered IP address is not in use, using ARP */
|
||||
#if DHCP_DOES_ARP_CHECK
|
||||
void dhcp_arp_reply(struct netif *netif, struct ip_addr *addr);
|
||||
void dhcp_arp_reply(struct netif *netif, ip_addr_t *addr);
|
||||
#endif
|
||||
|
||||
/** to be called every minute */
|
||||
@@ -136,66 +133,66 @@ void dhcp_coarse_tmr(void);
|
||||
void dhcp_fine_tmr(void);
|
||||
|
||||
/** DHCP message item offsets and length */
|
||||
#define DHCP_MSG_OFS (UDP_DATA_OFS)
|
||||
#define DHCP_OP_OFS (DHCP_MSG_OFS + 0)
|
||||
#define DHCP_HTYPE_OFS (DHCP_MSG_OFS + 1)
|
||||
#define DHCP_HLEN_OFS (DHCP_MSG_OFS + 2)
|
||||
#define DHCP_HOPS_OFS (DHCP_MSG_OFS + 3)
|
||||
#define DHCP_XID_OFS (DHCP_MSG_OFS + 4)
|
||||
#define DHCP_SECS_OFS (DHCP_MSG_OFS + 8)
|
||||
#define DHCP_FLAGS_OFS (DHCP_MSG_OFS + 10)
|
||||
#define DHCP_CIADDR_OFS (DHCP_MSG_OFS + 12)
|
||||
#define DHCP_YIADDR_OFS (DHCP_MSG_OFS + 16)
|
||||
#define DHCP_SIADDR_OFS (DHCP_MSG_OFS + 20)
|
||||
#define DHCP_GIADDR_OFS (DHCP_MSG_OFS + 24)
|
||||
#define DHCP_CHADDR_OFS (DHCP_MSG_OFS + 28)
|
||||
#define DHCP_SNAME_OFS (DHCP_MSG_OFS + 44)
|
||||
#define DHCP_FILE_OFS (DHCP_MSG_OFS + 108)
|
||||
#define DHCP_MSG_LEN 236
|
||||
#define DHCP_OP_OFS 0
|
||||
#define DHCP_HTYPE_OFS 1
|
||||
#define DHCP_HLEN_OFS 2
|
||||
#define DHCP_HOPS_OFS 3
|
||||
#define DHCP_XID_OFS 4
|
||||
#define DHCP_SECS_OFS 8
|
||||
#define DHCP_FLAGS_OFS 10
|
||||
#define DHCP_CIADDR_OFS 12
|
||||
#define DHCP_YIADDR_OFS 16
|
||||
#define DHCP_SIADDR_OFS 20
|
||||
#define DHCP_GIADDR_OFS 24
|
||||
#define DHCP_CHADDR_OFS 28
|
||||
#define DHCP_SNAME_OFS 44
|
||||
#define DHCP_FILE_OFS 108
|
||||
#define DHCP_MSG_LEN 236
|
||||
|
||||
#define DHCP_COOKIE_OFS (DHCP_MSG_OFS + DHCP_MSG_LEN)
|
||||
#define DHCP_OPTIONS_OFS (DHCP_MSG_OFS + DHCP_MSG_LEN + 4)
|
||||
#define DHCP_COOKIE_OFS DHCP_MSG_LEN
|
||||
#define DHCP_OPTIONS_OFS (DHCP_MSG_LEN + 4)
|
||||
|
||||
#define DHCP_CLIENT_PORT 68
|
||||
#define DHCP_SERVER_PORT 67
|
||||
#define DHCP_CLIENT_PORT 68
|
||||
#define DHCP_SERVER_PORT 67
|
||||
|
||||
/** DHCP client states */
|
||||
#define DHCP_REQUESTING 1
|
||||
#define DHCP_INIT 2
|
||||
#define DHCP_REBOOTING 3
|
||||
#define DHCP_REBINDING 4
|
||||
#define DHCP_RENEWING 5
|
||||
#define DHCP_SELECTING 6
|
||||
#define DHCP_INFORMING 7
|
||||
#define DHCP_CHECKING 8
|
||||
#define DHCP_PERMANENT 9
|
||||
#define DHCP_BOUND 10
|
||||
#define DHCP_OFF 0
|
||||
#define DHCP_REQUESTING 1
|
||||
#define DHCP_INIT 2
|
||||
#define DHCP_REBOOTING 3
|
||||
#define DHCP_REBINDING 4
|
||||
#define DHCP_RENEWING 5
|
||||
#define DHCP_SELECTING 6
|
||||
#define DHCP_INFORMING 7
|
||||
#define DHCP_CHECKING 8
|
||||
#define DHCP_PERMANENT 9
|
||||
#define DHCP_BOUND 10
|
||||
/** not yet implemented #define DHCP_RELEASING 11 */
|
||||
#define DHCP_BACKING_OFF 12
|
||||
#define DHCP_OFF 13
|
||||
#define DHCP_BACKING_OFF 12
|
||||
|
||||
/** AUTOIP cooperatation flags */
|
||||
#define DHCP_AUTOIP_COOP_STATE_OFF 0
|
||||
#define DHCP_AUTOIP_COOP_STATE_ON 1
|
||||
#define DHCP_AUTOIP_COOP_STATE_OFF 0
|
||||
#define DHCP_AUTOIP_COOP_STATE_ON 1
|
||||
|
||||
#define DHCP_BOOTREQUEST 1
|
||||
#define DHCP_BOOTREPLY 2
|
||||
#define DHCP_BOOTREQUEST 1
|
||||
#define DHCP_BOOTREPLY 2
|
||||
|
||||
/** DHCP message types */
|
||||
#define DHCP_DISCOVER 1
|
||||
#define DHCP_OFFER 2
|
||||
#define DHCP_REQUEST 3
|
||||
#define DHCP_DECLINE 4
|
||||
#define DHCP_ACK 5
|
||||
#define DHCP_NAK 6
|
||||
#define DHCP_RELEASE 7
|
||||
#define DHCP_INFORM 8
|
||||
#define DHCP_OFFER 2
|
||||
#define DHCP_REQUEST 3
|
||||
#define DHCP_DECLINE 4
|
||||
#define DHCP_ACK 5
|
||||
#define DHCP_NAK 6
|
||||
#define DHCP_RELEASE 7
|
||||
#define DHCP_INFORM 8
|
||||
|
||||
/** DHCP hardware type, currently only ethernet is supported */
|
||||
#define DHCP_HTYPE_ETH 1
|
||||
|
||||
#define DHCP_HLEN_ETH 6
|
||||
#define DHCP_MAGIC_COOKIE 0x63825363UL
|
||||
|
||||
#define DHCP_BROADCAST_FLAG 15
|
||||
#define DHCP_BROADCAST_MASK (1 << DHCP_FLAG_BROADCAST)
|
||||
/* This is a list of options for BOOTP and DHCP, see RFC 2132 for descriptions */
|
||||
|
||||
/** BootP options */
|
||||
#define DHCP_OPTION_PAD 0
|
||||
@@ -217,7 +214,6 @@ void dhcp_fine_tmr(void);
|
||||
#define DHCP_OPTION_MESSAGE_TYPE 53 /* RFC 2132 9.6, important for DHCP */
|
||||
#define DHCP_OPTION_MESSAGE_TYPE_LEN 1
|
||||
|
||||
|
||||
#define DHCP_OPTION_SERVER_ID 54 /* RFC 2132 9.7, server IP address */
|
||||
#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2132 9.8, requested option types */
|
||||
|
||||
|
||||
@@ -38,6 +38,10 @@
|
||||
|
||||
#if LWIP_DNS /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** DNS timer period */
|
||||
#define DNS_TMR_INTERVAL 1000
|
||||
|
||||
@@ -66,32 +70,55 @@
|
||||
#define DNS_RRCLASS_HS 4 /* Hesiod [Dyer 87] */
|
||||
#define DNS_RRCLASS_FLUSH 0x800 /* Flush bit */
|
||||
|
||||
/* The size used for the next line is rather a hack, but it prevents including socket.h in all files
|
||||
that include memp.h, and that would possibly break portability (since socket.h defines some types
|
||||
and constants possibly already define by the OS).
|
||||
Calculation rule:
|
||||
sizeof(struct addrinfo) + sizeof(struct sockaddr_in) + DNS_MAX_NAME_LENGTH + 1 byte zero-termination */
|
||||
#define NETDB_ELEM_SIZE (32 + 16 + DNS_MAX_NAME_LENGTH + 1)
|
||||
|
||||
#if DNS_LOCAL_HOSTLIST
|
||||
/** struct used for local host-list */
|
||||
struct local_hostlist_entry {
|
||||
/** static hostname */
|
||||
const char *name;
|
||||
/** static host address in network byteorder */
|
||||
ip_addr_t addr;
|
||||
struct local_hostlist_entry *next;
|
||||
};
|
||||
#if DNS_LOCAL_HOSTLIST_IS_DYNAMIC
|
||||
#ifndef DNS_LOCAL_HOSTLIST_MAX_NAMELEN
|
||||
#define DNS_LOCAL_HOSTLIST_MAX_NAMELEN DNS_MAX_NAME_LENGTH
|
||||
#endif
|
||||
#define LOCALHOSTLIST_ELEM_SIZE ((sizeof(struct local_hostlist_entry) + DNS_LOCAL_HOSTLIST_MAX_NAMELEN + 1))
|
||||
#endif /* DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
|
||||
#endif /* DNS_LOCAL_HOSTLIST */
|
||||
|
||||
/** Callback which is invoked when a hostname is found.
|
||||
* A function of this type must be implemented by the application using the DNS resolver.
|
||||
* @param name pointer to the name that was looked up.
|
||||
* @param ipaddr pointer to a struct ip_addr containing the IP address of the hostname,
|
||||
* @param ipaddr pointer to an ip_addr_t containing the IP address of the hostname,
|
||||
* or NULL if the name could not be found (or on any other error).
|
||||
* @param callback_arg a user-specified callback argument passed to dns_gethostbyname
|
||||
*/
|
||||
typedef void (*dns_found_callback)(const char *name, struct ip_addr *ipaddr, void *callback_arg);
|
||||
|
||||
typedef void (*dns_found_callback)(const char *name, ip_addr_t *ipaddr, void *callback_arg);
|
||||
|
||||
void dns_init(void);
|
||||
|
||||
void dns_tmr(void);
|
||||
|
||||
void dns_setserver(u8_t numdns, struct ip_addr *dnsserver);
|
||||
|
||||
struct ip_addr dns_getserver(u8_t numdns);
|
||||
|
||||
err_t dns_gethostbyname(const char *hostname, struct ip_addr *addr,
|
||||
void dns_setserver(u8_t numdns, ip_addr_t *dnsserver);
|
||||
ip_addr_t dns_getserver(u8_t numdns);
|
||||
err_t dns_gethostbyname(const char *hostname, ip_addr_t *addr,
|
||||
dns_found_callback found, void *callback_arg);
|
||||
|
||||
#if DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC
|
||||
int dns_local_removehost(const char *hostname, const struct ip_addr *addr);
|
||||
err_t dns_local_addhost(const char *hostname, const struct ip_addr *addr);
|
||||
int dns_local_removehost(const char *hostname, const ip_addr_t *addr);
|
||||
err_t dns_local_addhost(const char *hostname, const ip_addr_t *addr);
|
||||
#endif /* DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_DNS */
|
||||
|
||||
#endif /* __LWIP_DNS_H__ */
|
||||
|
||||
@@ -44,7 +44,7 @@ extern "C" {
|
||||
#ifdef LWIP_ERR_T
|
||||
typedef LWIP_ERR_T err_t;
|
||||
#else /* LWIP_ERR_T */
|
||||
typedef s8_t err_t;
|
||||
typedef s8_t err_t;
|
||||
#endif /* LWIP_ERR_T*/
|
||||
|
||||
/* Definitions for error constants. */
|
||||
@@ -54,24 +54,22 @@ typedef LWIP_ERR_T err_t;
|
||||
#define ERR_BUF -2 /* Buffer error. */
|
||||
#define ERR_TIMEOUT -3 /* Timeout. */
|
||||
#define ERR_RTE -4 /* Routing problem. */
|
||||
#define ERR_INPROGRESS -5 /* Operation in progress */
|
||||
#define ERR_VAL -6 /* Illegal value. */
|
||||
#define ERR_WOULDBLOCK -7 /* Operation would block. */
|
||||
#define ERR_USE -8 /* Address in use. */
|
||||
#define ERR_ISCONN -9 /* Already connected. */
|
||||
|
||||
#define ERR_IS_FATAL(e) ((e) < ERR_RTE)
|
||||
#define ERR_IS_FATAL(e) ((e) < ERR_ISCONN)
|
||||
|
||||
#define ERR_ABRT -5 /* Connection aborted. */
|
||||
#define ERR_RST -6 /* Connection reset. */
|
||||
#define ERR_CLSD -7 /* Connection closed. */
|
||||
#define ERR_CONN -8 /* Not connected. */
|
||||
#define ERR_ABRT -10 /* Connection aborted. */
|
||||
#define ERR_RST -11 /* Connection reset. */
|
||||
#define ERR_CLSD -12 /* Connection closed. */
|
||||
#define ERR_CONN -13 /* Not connected. */
|
||||
|
||||
#define ERR_VAL -9 /* Illegal value. */
|
||||
#define ERR_ARG -14 /* Illegal argument. */
|
||||
|
||||
#define ERR_ARG -10 /* Illegal argument. */
|
||||
|
||||
#define ERR_USE -11 /* Address in use. */
|
||||
|
||||
#define ERR_IF -12 /* Low-level netif error */
|
||||
#define ERR_ISCONN -13 /* Already connected. */
|
||||
|
||||
#define ERR_INPROGRESS -14 /* Operation in progress */
|
||||
#define ERR_IF -15 /* Low-level netif error */
|
||||
|
||||
|
||||
#ifdef LWIP_DEBUG
|
||||
|
||||
@@ -41,13 +41,13 @@ extern "C" {
|
||||
/** X.x.x: Major version of the stack */
|
||||
#define LWIP_VERSION_MAJOR 1U
|
||||
/** x.X.x: Minor version of the stack */
|
||||
#define LWIP_VERSION_MINOR 3U
|
||||
#define LWIP_VERSION_MINOR 4U
|
||||
/** x.x.X: Revision of the stack */
|
||||
#define LWIP_VERSION_REVISION 2U
|
||||
#define LWIP_VERSION_REVISION 1U
|
||||
/** For release candidates, this is set to 1..254
|
||||
* For official releases, this is set to 255 (LWIP_RC_RELEASE)
|
||||
* For development versions (CVS), this is set to 0 (LWIP_RC_DEVELOPMENT) */
|
||||
#define LWIP_VERSION_RC 255U
|
||||
#define LWIP_VERSION_RC 0U
|
||||
|
||||
/** LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases */
|
||||
#define LWIP_RC_RELEASE 255U
|
||||
|
||||
@@ -43,6 +43,7 @@ extern "C" {
|
||||
#include <stddef.h> /* for size_t */
|
||||
|
||||
typedef size_t mem_size_t;
|
||||
#define MEM_SIZE_F SZT_F
|
||||
|
||||
/* aliases for C library malloc() */
|
||||
#define mem_init()
|
||||
@@ -58,44 +59,59 @@ typedef size_t mem_size_t;
|
||||
#ifndef mem_calloc
|
||||
#define mem_calloc calloc
|
||||
#endif
|
||||
#ifndef mem_realloc
|
||||
static void *mem_realloc(void *mem, mem_size_t size)
|
||||
{
|
||||
LWIP_UNUSED_ARG(size);
|
||||
return mem;
|
||||
}
|
||||
/* Since there is no C library allocation function to shrink memory without
|
||||
moving it, define this to nothing. */
|
||||
#ifndef mem_trim
|
||||
#define mem_trim(mem, size) (mem)
|
||||
#endif
|
||||
#else /* MEM_LIBC_MALLOC */
|
||||
|
||||
/* MEM_SIZE would have to be aligned, but using 64000 here instead of
|
||||
* 65535 leaves some room for alignment...
|
||||
*/
|
||||
#if MEM_SIZE > 64000l
|
||||
#if MEM_SIZE > 64000L
|
||||
typedef u32_t mem_size_t;
|
||||
#define MEM_SIZE_F U32_F
|
||||
#else
|
||||
typedef u16_t mem_size_t;
|
||||
#define MEM_SIZE_F U16_F
|
||||
#endif /* MEM_SIZE > 64000 */
|
||||
|
||||
#if MEM_USE_POOLS
|
||||
/** mem_init is not used when using pools instead of a heap */
|
||||
#define mem_init()
|
||||
/** mem_realloc is not used when using pools instead of a heap:
|
||||
/** mem_trim is not used when using pools instead of a heap:
|
||||
we can't free part of a pool element and don't want to copy the rest */
|
||||
#define mem_realloc(mem, size) (mem)
|
||||
#define mem_trim(mem, size) (mem)
|
||||
#else /* MEM_USE_POOLS */
|
||||
/* lwIP alternative malloc */
|
||||
void mem_init(void);
|
||||
void *mem_realloc(void *mem, mem_size_t size);
|
||||
void *mem_trim(void *mem, mem_size_t size);
|
||||
#endif /* MEM_USE_POOLS */
|
||||
void *mem_malloc(mem_size_t size);
|
||||
void *mem_calloc(mem_size_t count, mem_size_t size);
|
||||
void mem_free(void *mem);
|
||||
#endif /* MEM_LIBC_MALLOC */
|
||||
|
||||
/** Calculate memory size for an aligned buffer - returns the next highest
|
||||
* multiple of MEM_ALIGNMENT (e.g. LWIP_MEM_ALIGN_SIZE(3) and
|
||||
* LWIP_MEM_ALIGN_SIZE(4) will both yield 4 for MEM_ALIGNMENT == 4).
|
||||
*/
|
||||
#ifndef LWIP_MEM_ALIGN_SIZE
|
||||
#define LWIP_MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1) & ~(MEM_ALIGNMENT-1))
|
||||
#endif
|
||||
|
||||
/** Calculate safe memory size for an aligned buffer when using an unaligned
|
||||
* type as storage. This includes a safety-margin on (MEM_ALIGNMENT - 1) at the
|
||||
* start (e.g. if buffer is u8_t[] and actual data will be u32_t*)
|
||||
*/
|
||||
#ifndef LWIP_MEM_ALIGN_BUFFER
|
||||
#define LWIP_MEM_ALIGN_BUFFER(size) (((size) + MEM_ALIGNMENT - 1))
|
||||
#endif
|
||||
|
||||
/** Align a memory pointer to the alignment defined by MEM_ALIGNMENT
|
||||
* so that ADDR % MEM_ALIGNMENT == 0
|
||||
*/
|
||||
#ifndef LWIP_MEM_ALIGN
|
||||
#define LWIP_MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1)))
|
||||
#endif
|
||||
|
||||
@@ -47,6 +47,9 @@ LWIP_MEMPOOL(TCP_SEG, MEMP_NUM_TCP_SEG, sizeof(struct tcp_seg),
|
||||
#if IP_REASSEMBLY
|
||||
LWIP_MEMPOOL(REASSDATA, MEMP_NUM_REASSDATA, sizeof(struct ip_reassdata), "REASSDATA")
|
||||
#endif /* IP_REASSEMBLY */
|
||||
#if IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF
|
||||
LWIP_MEMPOOL(FRAG_PBUF, MEMP_NUM_FRAG_PBUF, sizeof(struct pbuf_custom_ref),"FRAG_PBUF")
|
||||
#endif /* IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF */
|
||||
|
||||
#if LWIP_NETCONN
|
||||
LWIP_MEMPOOL(NETBUF, MEMP_NUM_NETBUF, sizeof(struct netbuf), "NETBUF")
|
||||
@@ -55,21 +58,38 @@ LWIP_MEMPOOL(NETCONN, MEMP_NUM_NETCONN, sizeof(struct netconn),
|
||||
|
||||
#if NO_SYS==0
|
||||
LWIP_MEMPOOL(TCPIP_MSG_API, MEMP_NUM_TCPIP_MSG_API, sizeof(struct tcpip_msg), "TCPIP_MSG_API")
|
||||
#if !LWIP_TCPIP_CORE_LOCKING_INPUT
|
||||
LWIP_MEMPOOL(TCPIP_MSG_INPKT,MEMP_NUM_TCPIP_MSG_INPKT, sizeof(struct tcpip_msg), "TCPIP_MSG_INPKT")
|
||||
#endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */
|
||||
#endif /* NO_SYS==0 */
|
||||
|
||||
#if ARP_QUEUEING
|
||||
#if LWIP_ARP && ARP_QUEUEING
|
||||
LWIP_MEMPOOL(ARP_QUEUE, MEMP_NUM_ARP_QUEUE, sizeof(struct etharp_q_entry), "ARP_QUEUE")
|
||||
#endif /* ARP_QUEUEING */
|
||||
#endif /* LWIP_ARP && ARP_QUEUEING */
|
||||
|
||||
#if LWIP_IGMP
|
||||
LWIP_MEMPOOL(IGMP_GROUP, MEMP_NUM_IGMP_GROUP, sizeof(struct igmp_group), "IGMP_GROUP")
|
||||
#endif /* LWIP_IGMP */
|
||||
|
||||
#if NO_SYS==0
|
||||
#if (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS)) /* LWIP_TIMERS */
|
||||
LWIP_MEMPOOL(SYS_TIMEOUT, MEMP_NUM_SYS_TIMEOUT, sizeof(struct sys_timeo), "SYS_TIMEOUT")
|
||||
#endif /* NO_SYS==0 */
|
||||
#endif /* LWIP_TIMERS */
|
||||
|
||||
#if LWIP_SNMP
|
||||
LWIP_MEMPOOL(SNMP_ROOTNODE, MEMP_NUM_SNMP_ROOTNODE, sizeof(struct mib_list_rootnode), "SNMP_ROOTNODE")
|
||||
LWIP_MEMPOOL(SNMP_NODE, MEMP_NUM_SNMP_NODE, sizeof(struct mib_list_node), "SNMP_NODE")
|
||||
LWIP_MEMPOOL(SNMP_VARBIND, MEMP_NUM_SNMP_VARBIND, sizeof(struct snmp_varbind), "SNMP_VARBIND")
|
||||
LWIP_MEMPOOL(SNMP_VALUE, MEMP_NUM_SNMP_VALUE, SNMP_MAX_VALUE_SIZE, "SNMP_VALUE")
|
||||
#endif /* LWIP_SNMP */
|
||||
#if LWIP_DNS && LWIP_SOCKET
|
||||
LWIP_MEMPOOL(NETDB, MEMP_NUM_NETDB, NETDB_ELEM_SIZE, "NETDB")
|
||||
#endif /* LWIP_DNS && LWIP_SOCKET */
|
||||
#if LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC
|
||||
LWIP_MEMPOOL(LOCALHOSTLIST, MEMP_NUM_LOCALHOSTLIST, LOCALHOSTLIST_ELEM_SIZE, "LOCALHOSTLIST")
|
||||
#endif /* LWIP_DNS && DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */
|
||||
#if PPP_SUPPORT && PPPOE_SUPPORT
|
||||
LWIP_MEMPOOL(PPPOE_IF, MEMP_NUM_PPPOE_INTERFACES, sizeof(struct pppoe_softc), "PPPOE_IF")
|
||||
#endif /* PPP_SUPPORT && PPPOE_SUPPORT */
|
||||
|
||||
/*
|
||||
* A list of pools of pbuf's used by LWIP.
|
||||
|
||||
@@ -40,14 +40,24 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** This netbuf has dest-addr/port set */
|
||||
#define NETBUF_FLAG_DESTADDR 0x01
|
||||
/** This netbuf includes a checksum */
|
||||
#define NETBUF_FLAG_CHKSUM 0x02
|
||||
|
||||
struct netbuf {
|
||||
struct pbuf *p, *ptr;
|
||||
struct ip_addr *addr;
|
||||
ip_addr_t addr;
|
||||
u16_t port;
|
||||
#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
u8_t flags;
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
u16_t toport_chksum;
|
||||
#if LWIP_NETBUF_RECVINFO
|
||||
struct ip_addr *toaddr;
|
||||
u16_t toport;
|
||||
ip_addr_t toaddr;
|
||||
#endif /* LWIP_NETBUF_RECVINFO */
|
||||
#endif /* LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY */
|
||||
};
|
||||
|
||||
/* Network buffer functions: */
|
||||
@@ -56,13 +66,12 @@ void netbuf_delete (struct netbuf *buf);
|
||||
void * netbuf_alloc (struct netbuf *buf, u16_t size);
|
||||
void netbuf_free (struct netbuf *buf);
|
||||
err_t netbuf_ref (struct netbuf *buf,
|
||||
const void *dataptr, u16_t size);
|
||||
const void *dataptr, u16_t size);
|
||||
void netbuf_chain (struct netbuf *head,
|
||||
struct netbuf *tail);
|
||||
|
||||
u16_t netbuf_len (struct netbuf *buf);
|
||||
err_t netbuf_data (struct netbuf *buf,
|
||||
void **dataptr, u16_t *len);
|
||||
void **dataptr, u16_t *len);
|
||||
s8_t netbuf_next (struct netbuf *buf);
|
||||
void netbuf_first (struct netbuf *buf);
|
||||
|
||||
@@ -72,12 +81,18 @@ void netbuf_first (struct netbuf *buf);
|
||||
#define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0)
|
||||
#define netbuf_take(buf, dataptr, len) pbuf_take((buf)->p, dataptr, len)
|
||||
#define netbuf_len(buf) ((buf)->p->tot_len)
|
||||
#define netbuf_fromaddr(buf) ((buf)->addr)
|
||||
#define netbuf_fromaddr(buf) (&((buf)->addr))
|
||||
#define netbuf_set_fromaddr(buf, fromaddr) ip_addr_set((&(buf)->addr), fromaddr)
|
||||
#define netbuf_fromport(buf) ((buf)->port)
|
||||
#if LWIP_NETBUF_RECVINFO
|
||||
#define netbuf_destaddr(buf) ((buf)->toaddr)
|
||||
#define netbuf_destport(buf) ((buf)->toport)
|
||||
#define netbuf_destaddr(buf) (&((buf)->toaddr))
|
||||
#define netbuf_set_destaddr(buf, destaddr) ip_addr_set((&(buf)->addr), destaddr)
|
||||
#define netbuf_destport(buf) (((buf)->flags & NETBUF_FLAG_DESTADDR) ? (buf)->toport_chksum : 0)
|
||||
#endif /* LWIP_NETBUF_RECVINFO */
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
#define netbuf_set_chksum(buf, chksum) do { (buf)->flags = NETBUF_FLAG_CHKSUM; \
|
||||
(buf)->toport_chksum = chksum; } while(0)
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
* Author: Simon Goldschmidt
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_NETDB_H__
|
||||
#define __LWIP_NETDB_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
@@ -33,8 +35,13 @@
|
||||
|
||||
#include <stddef.h> /* for size_t */
|
||||
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/sockets.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* some rarely used options */
|
||||
#ifndef LWIP_DNS_API_DECLARE_H_ERRNO
|
||||
#define LWIP_DNS_API_DECLARE_H_ERRNO 1
|
||||
@@ -108,4 +115,10 @@ int lwip_getaddrinfo(const char *nodename,
|
||||
lwip_getaddrinfo(nodname, servname, hints, res)
|
||||
#endif /* LWIP_COMPAT_SOCKETS */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_DNS && LWIP_SOCKET */
|
||||
|
||||
#endif /* __LWIP_NETDB_H__ */
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#if LWIP_DHCP
|
||||
struct dhcp;
|
||||
@@ -60,62 +60,113 @@ extern "C" {
|
||||
across all types of interfaces in use */
|
||||
#define NETIF_MAX_HWADDR_LEN 6U
|
||||
|
||||
/** TODO: define the use (where, when, whom) of netif flags */
|
||||
|
||||
/** whether the network interface is 'up'. this is
|
||||
/** Whether the network interface is 'up'. This is
|
||||
* a software flag used to control whether this network
|
||||
* interface is enabled and processes traffic.
|
||||
* It is set by the startup code (for static IP configuration) or
|
||||
* by dhcp/autoip when an address has been assigned.
|
||||
*/
|
||||
#define NETIF_FLAG_UP 0x01U
|
||||
/** if set, the netif has broadcast capability */
|
||||
/** If set, the netif has broadcast capability.
|
||||
* Set by the netif driver in its init function. */
|
||||
#define NETIF_FLAG_BROADCAST 0x02U
|
||||
/** if set, the netif is one end of a point-to-point connection */
|
||||
/** If set, the netif is one end of a point-to-point connection.
|
||||
* Set by the netif driver in its init function. */
|
||||
#define NETIF_FLAG_POINTTOPOINT 0x04U
|
||||
/** if set, the interface is configured using DHCP */
|
||||
/** If set, the interface is configured using DHCP.
|
||||
* Set by the DHCP code when starting or stopping DHCP. */
|
||||
#define NETIF_FLAG_DHCP 0x08U
|
||||
/** if set, the interface has an active link
|
||||
* (set by the network interface driver) */
|
||||
/** If set, the interface has an active link
|
||||
* (set by the network interface driver).
|
||||
* Either set by the netif driver in its init function (if the link
|
||||
* is up at that time) or at a later point once the link comes up
|
||||
* (if link detection is supported by the hardware). */
|
||||
#define NETIF_FLAG_LINK_UP 0x10U
|
||||
/** if set, the netif is an device using ARP */
|
||||
/** If set, the netif is an ethernet device using ARP.
|
||||
* Set by the netif driver in its init function.
|
||||
* Used to check input packet types and use of DHCP. */
|
||||
#define NETIF_FLAG_ETHARP 0x20U
|
||||
/** if set, the netif has IGMP capability */
|
||||
#define NETIF_FLAG_IGMP 0x40U
|
||||
/** If set, the netif is an ethernet device. It might not use
|
||||
* ARP or TCP/IP if it is used for PPPoE only.
|
||||
*/
|
||||
#define NETIF_FLAG_ETHERNET 0x40U
|
||||
/** If set, the netif has IGMP capability.
|
||||
* Set by the netif driver in its init function. */
|
||||
#define NETIF_FLAG_IGMP 0x80U
|
||||
|
||||
/** Function prototype for netif init functions. Set up flags and output/linkoutput
|
||||
* callback functions in this function.
|
||||
*
|
||||
* @param netif The netif to initialize
|
||||
*/
|
||||
typedef err_t (*netif_init_fn)(struct netif *netif);
|
||||
/** Function prototype for netif->input functions. This function is saved as 'input'
|
||||
* callback function in the netif struct. Call it when a packet has been received.
|
||||
*
|
||||
* @param p The received packet, copied into a pbuf
|
||||
* @param inp The netif which received the packet
|
||||
*/
|
||||
typedef err_t (*netif_input_fn)(struct pbuf *p, struct netif *inp);
|
||||
/** Function prototype for netif->output functions. Called by lwIP when a packet
|
||||
* shall be sent. For ethernet netif, set this to 'etharp_output' and set
|
||||
* 'linkoutput'.
|
||||
*
|
||||
* @param netif The netif which shall send a packet
|
||||
* @param p The packet to send (p->payload points to IP header)
|
||||
* @param ipaddr The IP address to which the packet shall be sent
|
||||
*/
|
||||
typedef err_t (*netif_output_fn)(struct netif *netif, struct pbuf *p,
|
||||
ip_addr_t *ipaddr);
|
||||
/** Function prototype for netif->linkoutput functions. Only used for ethernet
|
||||
* netifs. This function is called by ARP when a packet shall be sent.
|
||||
*
|
||||
* @param netif The netif which shall send a packet
|
||||
* @param p The packet to send (raw ethernet packet)
|
||||
*/
|
||||
typedef err_t (*netif_linkoutput_fn)(struct netif *netif, struct pbuf *p);
|
||||
/** Function prototype for netif status- or link-callback functions. */
|
||||
typedef void (*netif_status_callback_fn)(struct netif *netif);
|
||||
/** Function prototype for netif igmp_mac_filter functions */
|
||||
typedef err_t (*netif_igmp_mac_filter_fn)(struct netif *netif,
|
||||
ip_addr_t *group, u8_t action);
|
||||
|
||||
/** Generic data structure used for all lwIP network interfaces.
|
||||
* The following fields should be filled in by the initialization
|
||||
* function for the device driver: hwaddr_len, hwaddr[], mtu, flags */
|
||||
|
||||
struct netif {
|
||||
/** pointer to next in linked list */
|
||||
struct netif *next;
|
||||
|
||||
/** IP address configuration in network byte order */
|
||||
struct ip_addr ip_addr;
|
||||
struct ip_addr netmask;
|
||||
struct ip_addr gw;
|
||||
ip_addr_t ip_addr;
|
||||
ip_addr_t netmask;
|
||||
ip_addr_t gw;
|
||||
|
||||
/** This function is called by the network device driver
|
||||
* to pass a packet up the TCP/IP stack. */
|
||||
err_t (* input)(struct pbuf *p, struct netif *inp);
|
||||
netif_input_fn input;
|
||||
/** This function is called by the IP module when it wants
|
||||
* to send a packet on the interface. This function typically
|
||||
* first resolves the hardware address, then sends the packet. */
|
||||
err_t (* output)(struct netif *netif, struct pbuf *p,
|
||||
struct ip_addr *ipaddr);
|
||||
netif_output_fn output;
|
||||
/** This function is called by the ARP module when it wants
|
||||
* to send a packet on the interface. This function outputs
|
||||
* the pbuf as-is on the link medium. */
|
||||
err_t (* linkoutput)(struct netif *netif, struct pbuf *p);
|
||||
netif_linkoutput_fn linkoutput;
|
||||
#if LWIP_NETIF_STATUS_CALLBACK
|
||||
/** This function is called when the netif state is set to up or down
|
||||
*/
|
||||
void (* status_callback)(struct netif *netif);
|
||||
netif_status_callback_fn status_callback;
|
||||
#endif /* LWIP_NETIF_STATUS_CALLBACK */
|
||||
#if LWIP_NETIF_LINK_CALLBACK
|
||||
/** This function is called when the netif link is set to up or down
|
||||
*/
|
||||
void (* link_callback)(struct netif *netif);
|
||||
netif_status_callback_fn link_callback;
|
||||
#endif /* LWIP_NETIF_LINK_CALLBACK */
|
||||
#if LWIP_NETIF_REMOVE_CALLBACK
|
||||
/** This function is called when the netif has been removed */
|
||||
netif_status_callback_fn remove_callback;
|
||||
#endif /* LWIP_NETIF_REMOVE_CALLBACK */
|
||||
/** This field can be set by the device driver and could point
|
||||
* to state information for the device. */
|
||||
void *state;
|
||||
@@ -161,8 +212,9 @@ struct netif {
|
||||
u32_t ifoutdiscards;
|
||||
#endif /* LWIP_SNMP */
|
||||
#if LWIP_IGMP
|
||||
/* This function could be called to add or delete a entry in the multicast filter table of the ethernet MAC.*/
|
||||
err_t (*igmp_mac_filter)( struct netif *netif, struct ip_addr *group, u8_t action);
|
||||
/** This function could be called to add or delete a entry in the multicast
|
||||
filter table of the ethernet MAC.*/
|
||||
netif_igmp_mac_filter_fn igmp_mac_filter;
|
||||
#endif /* LWIP_IGMP */
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
u8_t *addr_hint;
|
||||
@@ -180,18 +232,18 @@ struct netif {
|
||||
#if LWIP_SNMP
|
||||
#define NETIF_INIT_SNMP(netif, type, speed) \
|
||||
/* use "snmp_ifType" enum from snmp.h for "type", snmp_ifType_ethernet_csmacd by example */ \
|
||||
netif->link_type = type; \
|
||||
(netif)->link_type = (type); \
|
||||
/* your link speed here (units: bits per second) */ \
|
||||
netif->link_speed = speed; \
|
||||
netif->ts = 0; \
|
||||
netif->ifinoctets = 0; \
|
||||
netif->ifinucastpkts = 0; \
|
||||
netif->ifinnucastpkts = 0; \
|
||||
netif->ifindiscards = 0; \
|
||||
netif->ifoutoctets = 0; \
|
||||
netif->ifoutucastpkts = 0; \
|
||||
netif->ifoutnucastpkts = 0; \
|
||||
netif->ifoutdiscards = 0
|
||||
(netif)->link_speed = (speed); \
|
||||
(netif)->ts = 0; \
|
||||
(netif)->ifinoctets = 0; \
|
||||
(netif)->ifinucastpkts = 0; \
|
||||
(netif)->ifinnucastpkts = 0; \
|
||||
(netif)->ifindiscards = 0; \
|
||||
(netif)->ifoutoctets = 0; \
|
||||
(netif)->ifoutucastpkts = 0; \
|
||||
(netif)->ifoutnucastpkts = 0; \
|
||||
(netif)->ifoutdiscards = 0
|
||||
#else /* LWIP_SNMP */
|
||||
#define NETIF_INIT_SNMP(netif, type, speed)
|
||||
#endif /* LWIP_SNMP */
|
||||
@@ -202,17 +254,14 @@ extern struct netif *netif_list;
|
||||
/** The default network interface. */
|
||||
extern struct netif *netif_default;
|
||||
|
||||
#define netif_init() /* Compatibility define, not init needed. */
|
||||
void netif_init(void);
|
||||
|
||||
struct netif *netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
|
||||
struct ip_addr *gw,
|
||||
void *state,
|
||||
err_t (* init)(struct netif *netif),
|
||||
err_t (* input)(struct pbuf *p, struct netif *netif));
|
||||
struct netif *netif_add(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
|
||||
ip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input);
|
||||
|
||||
void
|
||||
netif_set_addr(struct netif *netif,struct ip_addr *ipaddr, struct ip_addr *netmask,
|
||||
struct ip_addr *gw);
|
||||
netif_set_addr(struct netif *netif, ip_addr_t *ipaddr, ip_addr_t *netmask,
|
||||
ip_addr_t *gw);
|
||||
void netif_remove(struct netif * netif);
|
||||
|
||||
/* Returns a network interface given its name. The name is of the form
|
||||
@@ -223,41 +272,57 @@ struct netif *netif_find(char *name);
|
||||
|
||||
void netif_set_default(struct netif *netif);
|
||||
|
||||
void netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr);
|
||||
void netif_set_netmask(struct netif *netif, struct ip_addr *netmask);
|
||||
void netif_set_gw(struct netif *netif, struct ip_addr *gw);
|
||||
void netif_set_ipaddr(struct netif *netif, ip_addr_t *ipaddr);
|
||||
void netif_set_netmask(struct netif *netif, ip_addr_t *netmask);
|
||||
void netif_set_gw(struct netif *netif, ip_addr_t *gw);
|
||||
|
||||
void netif_set_up(struct netif *netif);
|
||||
void netif_set_down(struct netif *netif);
|
||||
u8_t netif_is_up(struct netif *netif);
|
||||
/** Ask if an interface is up */
|
||||
#define netif_is_up(netif) (((netif)->flags & NETIF_FLAG_UP) ? (u8_t)1 : (u8_t)0)
|
||||
|
||||
#if LWIP_NETIF_STATUS_CALLBACK
|
||||
/*
|
||||
* Set callback to be called when interface is brought up/down
|
||||
*/
|
||||
void netif_set_status_callback(struct netif *netif, void (* status_callback)(struct netif *netif));
|
||||
void netif_set_status_callback(struct netif *netif, netif_status_callback_fn status_callback);
|
||||
#endif /* LWIP_NETIF_STATUS_CALLBACK */
|
||||
#if LWIP_NETIF_REMOVE_CALLBACK
|
||||
void netif_set_remove_callback(struct netif *netif, netif_status_callback_fn remove_callback);
|
||||
#endif /* LWIP_NETIF_REMOVE_CALLBACK */
|
||||
|
||||
#if LWIP_NETIF_LINK_CALLBACK
|
||||
void netif_set_link_up(struct netif *netif);
|
||||
void netif_set_link_down(struct netif *netif);
|
||||
u8_t netif_is_link_up(struct netif *netif);
|
||||
/*
|
||||
* Set callback to be called when link is brought up/down
|
||||
*/
|
||||
void netif_set_link_callback(struct netif *netif, void (* link_callback)(struct netif *netif));
|
||||
/** Ask if a link is up */
|
||||
#define netif_is_link_up(netif) (((netif)->flags & NETIF_FLAG_LINK_UP) ? (u8_t)1 : (u8_t)0)
|
||||
|
||||
#if LWIP_NETIF_LINK_CALLBACK
|
||||
void netif_set_link_callback(struct netif *netif, netif_status_callback_fn link_callback);
|
||||
#endif /* LWIP_NETIF_LINK_CALLBACK */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#if LWIP_NETIF_HOSTNAME
|
||||
#define netif_set_hostname(netif, name) do { if((netif) != NULL) { (netif)->hostname = name; }}while(0)
|
||||
#define netif_get_hostname(netif) (((netif) != NULL) ? ((netif)->hostname) : NULL)
|
||||
#endif /* LWIP_NETIF_HOSTNAME */
|
||||
|
||||
#if LWIP_IGMP
|
||||
#define netif_set_igmp_mac_filter(netif, function) do { if((netif) != NULL) { (netif)->igmp_mac_filter = function; }}while(0)
|
||||
#define netif_get_igmp_mac_filter(netif) (((netif) != NULL) ? ((netif)->igmp_mac_filter) : NULL)
|
||||
#endif /* LWIP_IGMP */
|
||||
|
||||
#if ENABLE_LOOPBACK
|
||||
err_t netif_loop_output(struct netif *netif, struct pbuf *p, struct ip_addr *dest_ip);
|
||||
err_t netif_loop_output(struct netif *netif, struct pbuf *p, ip_addr_t *dest_ip);
|
||||
void netif_poll(struct netif *netif);
|
||||
#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
|
||||
void netif_poll_all(void);
|
||||
#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
||||
#endif /* ENABLE_LOOPBACK */
|
||||
|
||||
#if LWIP_NETIF_HWADDRHINT
|
||||
#define NETIF_SET_HWADDRHINT(netif, hint) ((netif)->addr_hint = (hint))
|
||||
#else /* LWIP_NETIF_HWADDRHINT */
|
||||
#define NETIF_SET_HWADDRHINT(netif, hint)
|
||||
#endif /* LWIP_NETIF_HWADDRHINT */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __LWIP_NETIF_H__ */
|
||||
|
||||
@@ -41,6 +41,9 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*netifapi_void_fn)(struct netif *netif);
|
||||
typedef err_t (*netifapi_errt_fn)(struct netif *netif);
|
||||
|
||||
struct netifapi_msg_msg {
|
||||
#if !LWIP_TCPIP_CORE_LOCKING
|
||||
sys_sem_t sem;
|
||||
@@ -49,16 +52,16 @@ struct netifapi_msg_msg {
|
||||
struct netif *netif;
|
||||
union {
|
||||
struct {
|
||||
struct ip_addr *ipaddr;
|
||||
struct ip_addr *netmask;
|
||||
struct ip_addr *gw;
|
||||
ip_addr_t *ipaddr;
|
||||
ip_addr_t *netmask;
|
||||
ip_addr_t *gw;
|
||||
void *state;
|
||||
err_t (* init) (struct netif *netif);
|
||||
err_t (* input)(struct pbuf *p, struct netif *netif);
|
||||
netif_init_fn init;
|
||||
netif_input_fn input;
|
||||
} add;
|
||||
struct {
|
||||
void (* voidfunc)(struct netif *netif);
|
||||
err_t (* errtfunc)(struct netif *netif);
|
||||
netifapi_void_fn voidfunc;
|
||||
netifapi_errt_fn errtfunc;
|
||||
} common;
|
||||
} msg;
|
||||
};
|
||||
@@ -71,21 +74,21 @@ struct netifapi_msg {
|
||||
|
||||
/* API for application */
|
||||
err_t netifapi_netif_add ( struct netif *netif,
|
||||
struct ip_addr *ipaddr,
|
||||
struct ip_addr *netmask,
|
||||
struct ip_addr *gw,
|
||||
ip_addr_t *ipaddr,
|
||||
ip_addr_t *netmask,
|
||||
ip_addr_t *gw,
|
||||
void *state,
|
||||
err_t (* init)(struct netif *netif),
|
||||
err_t (* input)(struct pbuf *p, struct netif *netif) );
|
||||
netif_init_fn init,
|
||||
netif_input_fn input);
|
||||
|
||||
err_t netifapi_netif_set_addr ( struct netif *netif,
|
||||
struct ip_addr *ipaddr,
|
||||
struct ip_addr *netmask,
|
||||
struct ip_addr *gw );
|
||||
ip_addr_t *ipaddr,
|
||||
ip_addr_t *netmask,
|
||||
ip_addr_t *gw );
|
||||
|
||||
err_t netifapi_netif_common ( struct netif *netif,
|
||||
void (* voidfunc)(struct netif *netif),
|
||||
err_t (* errtfunc)(struct netif *netif) );
|
||||
netifapi_void_fn voidfunc,
|
||||
netifapi_errt_fn errtfunc);
|
||||
|
||||
#define netifapi_netif_remove(n) netifapi_netif_common(n, netif_remove, NULL)
|
||||
#define netifapi_netif_set_up(n) netifapi_netif_common(n, netif_set_up, NULL)
|
||||
|
||||
@@ -68,6 +68,14 @@
|
||||
#define NO_SYS 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* NO_SYS_NO_TIMERS==1: Drop support for sys_timeout when NO_SYS==1
|
||||
* Mainly for compatibility to old versions.
|
||||
*/
|
||||
#ifndef NO_SYS_NO_TIMERS
|
||||
#define NO_SYS_NO_TIMERS 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MEMCPY: override this if you have a faster implementation at hand than the
|
||||
* one included in your C library
|
||||
@@ -124,6 +132,15 @@
|
||||
#define MEM_SIZE 1600
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MEMP_SEPARATE_POOLS: if defined to 1, each pool is placed in its own array.
|
||||
* This can be used to individually change the location of each pool.
|
||||
* Default is one big array for all pools
|
||||
*/
|
||||
#ifndef MEMP_SEPARATE_POOLS
|
||||
#define MEMP_SEPARATE_POOLS 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MEMP_OVERFLOW_CHECK: memp overflow protection reserves a configurable
|
||||
* amount of bytes before and after each memp element in every pool and fills
|
||||
@@ -251,13 +268,24 @@
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MEMP_NUM_REASSDATA: the number of simultaneously IP packets queued for
|
||||
* MEMP_NUM_REASSDATA: the number of IP packets simultaneously queued for
|
||||
* reassembly (whole packets, not fragments!)
|
||||
*/
|
||||
#ifndef MEMP_NUM_REASSDATA
|
||||
#define MEMP_NUM_REASSDATA 5
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MEMP_NUM_FRAG_PBUF: the number of IP fragments simultaneously sent
|
||||
* (fragments, not whole packets!).
|
||||
* This is only used with IP_FRAG_USES_STATIC_BUF==0 and
|
||||
* LWIP_NETIF_TX_SINGLE_PBUF==0 and only has to be > 1 with DMA-enabled MACs
|
||||
* where the packet is not yet sent when netif->output returns.
|
||||
*/
|
||||
#ifndef MEMP_NUM_FRAG_PBUF
|
||||
#define MEMP_NUM_FRAG_PBUF 15
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MEMP_NUM_ARP_QUEUE: the number of simulateously queued outgoing
|
||||
* packets (pbufs) that are waiting for an ARP request (to resolve
|
||||
@@ -281,9 +309,11 @@
|
||||
/**
|
||||
* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active timeouts.
|
||||
* (requires NO_SYS==0)
|
||||
* The default number of timeouts is calculated here for all enabled modules.
|
||||
* The formula expects settings to be either '0' or '1'.
|
||||
*/
|
||||
#ifndef MEMP_NUM_SYS_TIMEOUT
|
||||
#define MEMP_NUM_SYS_TIMEOUT 3
|
||||
#define MEMP_NUM_SYS_TIMEOUT (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT)
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -320,6 +350,63 @@
|
||||
#define MEMP_NUM_TCPIP_MSG_INPKT 8
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MEMP_NUM_SNMP_NODE: the number of leafs in the SNMP tree.
|
||||
*/
|
||||
#ifndef MEMP_NUM_SNMP_NODE
|
||||
#define MEMP_NUM_SNMP_NODE 50
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MEMP_NUM_SNMP_ROOTNODE: the number of branches in the SNMP tree.
|
||||
* Every branch has one leaf (MEMP_NUM_SNMP_NODE) at least!
|
||||
*/
|
||||
#ifndef MEMP_NUM_SNMP_ROOTNODE
|
||||
#define MEMP_NUM_SNMP_ROOTNODE 30
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MEMP_NUM_SNMP_VARBIND: the number of concurrent requests (does not have to
|
||||
* be changed normally) - 2 of these are used per request (1 for input,
|
||||
* 1 for output)
|
||||
*/
|
||||
#ifndef MEMP_NUM_SNMP_VARBIND
|
||||
#define MEMP_NUM_SNMP_VARBIND 2
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MEMP_NUM_SNMP_VALUE: the number of OID or values concurrently used
|
||||
* (does not have to be changed normally) - 3 of these are used per request
|
||||
* (1 for the value read and 2 for OIDs - input and output)
|
||||
*/
|
||||
#ifndef MEMP_NUM_SNMP_VALUE
|
||||
#define MEMP_NUM_SNMP_VALUE 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MEMP_NUM_NETDB: the number of concurrently running lwip_addrinfo() calls
|
||||
* (before freeing the corresponding memory using lwip_freeaddrinfo()).
|
||||
*/
|
||||
#ifndef MEMP_NUM_NETDB
|
||||
#define MEMP_NUM_NETDB 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MEMP_NUM_LOCALHOSTLIST: the number of host entries in the local host list
|
||||
* if DNS_LOCAL_HOSTLIST_IS_DYNAMIC==1.
|
||||
*/
|
||||
#ifndef MEMP_NUM_LOCALHOSTLIST
|
||||
#define MEMP_NUM_LOCALHOSTLIST 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MEMP_NUM_PPPOE_INTERFACES: the number of concurrently active PPPoE
|
||||
* interfaces (only used with PPPOE_SUPPORT==1)
|
||||
*/
|
||||
#ifndef MEMP_NUM_PPPOE_INTERFACES
|
||||
#define MEMP_NUM_PPPOE_INTERFACES 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* PBUF_POOL_SIZE: the number of buffers in the pbuf pool.
|
||||
*/
|
||||
@@ -347,11 +434,14 @@
|
||||
#endif
|
||||
|
||||
/**
|
||||
* ARP_QUEUEING==1: Outgoing packets are queued during hardware address
|
||||
* resolution.
|
||||
* ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address
|
||||
* resolution. By default, only the most recent packet is queued per IP address.
|
||||
* This is sufficient for most protocols and mainly reduces TCP connection
|
||||
* startup time. Set this to 1 if you know your application sends more than one
|
||||
* packet in a row to an IP address that is not in the ARP cache.
|
||||
*/
|
||||
#ifndef ARP_QUEUEING
|
||||
#define ARP_QUEUEING 1
|
||||
#define ARP_QUEUEING 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -361,9 +451,11 @@
|
||||
* correct addresses, or as a limited approach to attempt to handle
|
||||
* spoofing. If disabled, lwIP will need to make a new ARP request if
|
||||
* the peer is not already in the ARP table, adding a little latency.
|
||||
* The peer *is* in the ARP table if it requested our address before.
|
||||
* Also notice that this slows down input processing of every IP packet!
|
||||
*/
|
||||
#ifndef ETHARP_TRUST_IP_MAC
|
||||
#define ETHARP_TRUST_IP_MAC 1
|
||||
#define ETHARP_TRUST_IP_MAC 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -371,11 +463,37 @@
|
||||
* Additionally, you can define ETHARP_VLAN_CHECK to an u16_t VLAN ID to check.
|
||||
* If ETHARP_VLAN_CHECK is defined, only VLAN-traffic for this VLAN is accepted.
|
||||
* If ETHARP_VLAN_CHECK is not defined, all traffic is accepted.
|
||||
* Alternatively, define a function/define ETHARP_VLAN_CHECK_FN(eth_hdr, vlan)
|
||||
* that returns 1 to accept a packet or 0 to drop a packet.
|
||||
*/
|
||||
#ifndef ETHARP_SUPPORT_VLAN
|
||||
#define ETHARP_SUPPORT_VLAN 0
|
||||
#endif
|
||||
|
||||
/** LWIP_ETHERNET==1: enable ethernet support for PPPoE even though ARP
|
||||
* might be disabled
|
||||
*/
|
||||
#ifndef LWIP_ETHERNET
|
||||
#define LWIP_ETHERNET (LWIP_ARP || PPPOE_SUPPORT)
|
||||
#endif
|
||||
|
||||
/** ETH_PAD_SIZE: number of bytes added before the ethernet header to ensure
|
||||
* alignment of payload after that header. Since the header is 14 bytes long,
|
||||
* without this padding e.g. addresses in the IP header will not be aligned
|
||||
* on a 32-bit boundary, so setting this to 2 can speed up 32-bit-platforms.
|
||||
*/
|
||||
#ifndef ETH_PAD_SIZE
|
||||
#define ETH_PAD_SIZE 0
|
||||
#endif
|
||||
|
||||
/** ETHARP_SUPPORT_STATIC_ENTRIES==1: enable code to support static ARP table
|
||||
* entries (using etharp_add_static_entry/etharp_remove_static_entry).
|
||||
*/
|
||||
#ifndef ETHARP_SUPPORT_STATIC_ENTRIES
|
||||
#define ETHARP_SUPPORT_STATIC_ENTRIES 0
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
--------------------------------
|
||||
---------- IP options ----------
|
||||
@@ -439,10 +557,12 @@
|
||||
/**
|
||||
* IP_FRAG_USES_STATIC_BUF==1: Use a static MTU-sized buffer for IP
|
||||
* fragmentation. Otherwise pbufs are allocated and reference the original
|
||||
* packet data to be fragmented.
|
||||
* packet data to be fragmented (or with LWIP_NETIF_TX_SINGLE_PBUF==1,
|
||||
* new PBUF_RAM pbufs are used for fragments).
|
||||
* ATTENTION: IP_FRAG_USES_STATIC_BUF==1 may not be used for DMA-enabled MACs!
|
||||
*/
|
||||
#ifndef IP_FRAG_USES_STATIC_BUF
|
||||
#define IP_FRAG_USES_STATIC_BUF 1
|
||||
#define IP_FRAG_USES_STATIC_BUF 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -477,6 +597,26 @@
|
||||
#define IP_SOF_BROADCAST_RECV 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* IP_FORWARD_ALLOW_TX_ON_RX_NETIF==1: allow ip_forward() to send packets back
|
||||
* out on the netif where it was received. This should only be used for
|
||||
* wireless networks.
|
||||
* ATTENTION: When this is 1, make sure your netif driver correctly marks incoming
|
||||
* link-layer-broadcast/multicast packets as such using the corresponding pbuf flags!
|
||||
*/
|
||||
#ifndef IP_FORWARD_ALLOW_TX_ON_RX_NETIF
|
||||
#define IP_FORWARD_ALLOW_TX_ON_RX_NETIF 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS==1: randomize the local port for the first
|
||||
* local TCP/UDP pcb (default==0). This can prevent creating predictable port
|
||||
* numbers after booting a device.
|
||||
*/
|
||||
#ifndef LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS
|
||||
#define LWIP_RANDOMIZE_INITIAL_LOCAL_PORTS 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
----------------------------------
|
||||
---------- ICMP options ----------
|
||||
@@ -595,7 +735,8 @@
|
||||
|
||||
/**
|
||||
* SNMP_CONCURRENT_REQUESTS: Number of concurrent requests the module will
|
||||
* allow. At least one request buffer is required.
|
||||
* allow. At least one request buffer is required.
|
||||
* Does not have to be changed unless external MIBs answer request asynchronously
|
||||
*/
|
||||
#ifndef SNMP_CONCURRENT_REQUESTS
|
||||
#define SNMP_CONCURRENT_REQUESTS 1
|
||||
@@ -611,6 +752,8 @@
|
||||
|
||||
/**
|
||||
* SNMP_PRIVATE_MIB:
|
||||
* When using a private MIB, you have to create a file 'private_mib.h' that contains
|
||||
* a 'struct mib_array_node mib_private' which contains your MIB.
|
||||
*/
|
||||
#ifndef SNMP_PRIVATE_MIB
|
||||
#define SNMP_PRIVATE_MIB 0
|
||||
@@ -625,6 +768,31 @@
|
||||
#define SNMP_SAFE_REQUESTS 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The maximum length of strings used. This affects the size of
|
||||
* MEMP_SNMP_VALUE elements.
|
||||
*/
|
||||
#ifndef SNMP_MAX_OCTET_STRING_LEN
|
||||
#define SNMP_MAX_OCTET_STRING_LEN 127
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The maximum depth of the SNMP tree.
|
||||
* With private MIBs enabled, this depends on your MIB!
|
||||
* This affects the size of MEMP_SNMP_VALUE elements.
|
||||
*/
|
||||
#ifndef SNMP_MAX_TREE_DEPTH
|
||||
#define SNMP_MAX_TREE_DEPTH 15
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The size of the MEMP_SNMP_VALUE elements, normally calculated from
|
||||
* SNMP_MAX_OCTET_STRING_LEN and SNMP_MAX_TREE_DEPTH.
|
||||
*/
|
||||
#ifndef SNMP_MAX_VALUE_SIZE
|
||||
#define SNMP_MAX_VALUE_SIZE LWIP_MAX((SNMP_MAX_OCTET_STRING_LEN)+1, sizeof(s32_t)*(SNMP_MAX_TREE_DEPTH))
|
||||
#endif
|
||||
|
||||
/*
|
||||
----------------------------------
|
||||
---------- IGMP options ----------
|
||||
@@ -670,13 +838,6 @@
|
||||
#define DNS_DOES_NAME_CHECK 1
|
||||
#endif
|
||||
|
||||
/** DNS use a local buffer if DNS_USES_STATIC_BUF=0, a static one if
|
||||
DNS_USES_STATIC_BUF=1, or a dynamic one if DNS_USES_STATIC_BUF=2.
|
||||
The buffer will be of size DNS_MSG_SIZE */
|
||||
#ifndef DNS_USES_STATIC_BUF
|
||||
#define DNS_USES_STATIC_BUF 1
|
||||
#endif
|
||||
|
||||
/** DNS message max. size. Default value is RFC compliant. */
|
||||
#ifndef DNS_MSG_SIZE
|
||||
#define DNS_MSG_SIZE 512
|
||||
@@ -809,10 +970,11 @@
|
||||
|
||||
|
||||
/**
|
||||
* TCP_SND_BUF: TCP sender buffer space (bytes).
|
||||
* TCP_SND_BUF: TCP sender buffer space (bytes).
|
||||
* To achieve good performance, this should be at least 2 * TCP_MSS.
|
||||
*/
|
||||
#ifndef TCP_SND_BUF
|
||||
#define TCP_SND_BUF 256
|
||||
#define TCP_SND_BUF (2 * TCP_MSS)
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -820,16 +982,41 @@
|
||||
* as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work.
|
||||
*/
|
||||
#ifndef TCP_SND_QUEUELEN
|
||||
#define TCP_SND_QUEUELEN (4 * (TCP_SND_BUF)/(TCP_MSS))
|
||||
#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS))
|
||||
#endif
|
||||
|
||||
/**
|
||||
* TCP_SNDLOWAT: TCP writable space (bytes). This must be less than or equal
|
||||
* to TCP_SND_BUF. It is the amount of space which must be available in the
|
||||
* TCP snd_buf for select to return writable.
|
||||
* TCP_SNDLOWAT: TCP writable space (bytes). This must be less than
|
||||
* TCP_SND_BUF. It is the amount of space which must be available in the
|
||||
* TCP snd_buf for select to return writable (combined with TCP_SNDQUEUELOWAT).
|
||||
*/
|
||||
#ifndef TCP_SNDLOWAT
|
||||
#define TCP_SNDLOWAT ((TCP_SND_BUF)/2)
|
||||
#define TCP_SNDLOWAT LWIP_MIN(LWIP_MAX(((TCP_SND_BUF)/2), (2 * TCP_MSS) + 1), (TCP_SND_BUF) - 1)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* TCP_SNDQUEUELOWAT: TCP writable bufs (pbuf count). This must be less
|
||||
* than TCP_SND_QUEUELEN. If the number of pbufs queued on a pcb drops below
|
||||
* this number, select returns writable (combined with TCP_SNDLOWAT).
|
||||
*/
|
||||
#ifndef TCP_SNDQUEUELOWAT
|
||||
#define TCP_SNDQUEUELOWAT LWIP_MAX(((TCP_SND_QUEUELEN)/2), 5)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* TCP_OOSEQ_MAX_BYTES: The maximum number of bytes queued on ooseq per pcb.
|
||||
* Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==0.
|
||||
*/
|
||||
#ifndef TCP_OOSEQ_MAX_BYTES
|
||||
#define TCP_OOSEQ_MAX_BYTES 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* TCP_OOSEQ_MAX_PBUFS: The maximum number of pbufs queued on ooseq per pcb.
|
||||
* Default is 0 (no limit). Only valid for TCP_QUEUE_OOSEQ==0.
|
||||
*/
|
||||
#ifndef TCP_OOSEQ_MAX_PBUFS
|
||||
#define TCP_OOSEQ_MAX_PBUFS 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -848,6 +1035,24 @@
|
||||
#define TCP_DEFAULT_LISTEN_BACKLOG 0xff
|
||||
#endif
|
||||
|
||||
/**
|
||||
* TCP_OVERSIZE: The maximum number of bytes that tcp_write may
|
||||
* allocate ahead of time in an attempt to create shorter pbuf chains
|
||||
* for transmission. The meaningful range is 0 to TCP_MSS. Some
|
||||
* suggested values are:
|
||||
*
|
||||
* 0: Disable oversized allocation. Each tcp_write() allocates a new
|
||||
pbuf (old behaviour).
|
||||
* 1: Allocate size-aligned pbufs with minimal excess. Use this if your
|
||||
* scatter-gather DMA requires aligned fragments.
|
||||
* 128: Limit the pbuf/memory overhead to 20%.
|
||||
* TCP_MSS: Try to create unfragmented TCP packets.
|
||||
* TCP_MSS/4: Try to create 4 fragments or less per TCP packet.
|
||||
*/
|
||||
#ifndef TCP_OVERSIZE
|
||||
#define TCP_OVERSIZE TCP_MSS
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_TCP_TIMESTAMPS==1: support the TCP timestamp option.
|
||||
*/
|
||||
@@ -868,14 +1073,11 @@
|
||||
* LWIP_EVENT_API==1: The user defines lwip_tcp_event() to receive all
|
||||
* events (accept, sent, etc) that happen in the system.
|
||||
* LWIP_CALLBACK_API==1: The PCB callback function is called directly
|
||||
* for the event.
|
||||
* for the event. This is the default.
|
||||
*/
|
||||
#ifndef LWIP_EVENT_API
|
||||
#if !defined(LWIP_EVENT_API) && !defined(LWIP_CALLBACK_API)
|
||||
#define LWIP_EVENT_API 0
|
||||
#define LWIP_CALLBACK_API 1
|
||||
#else
|
||||
#define LWIP_EVENT_API 1
|
||||
#define LWIP_CALLBACK_API 0
|
||||
#endif
|
||||
|
||||
|
||||
@@ -890,7 +1092,7 @@
|
||||
* Ethernet.
|
||||
*/
|
||||
#ifndef PBUF_LINK_HLEN
|
||||
#define PBUF_LINK_HLEN 14
|
||||
#define PBUF_LINK_HLEN (14 + ETH_PAD_SIZE)
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -938,6 +1140,14 @@
|
||||
#define LWIP_NETIF_LINK_CALLBACK 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_NETIF_REMOVE_CALLBACK==1: Support a callback function that is called
|
||||
* when a netif has been removed
|
||||
*/
|
||||
#ifndef LWIP_NETIF_REMOVE_CALLBACK
|
||||
#define LWIP_NETIF_REMOVE_CALLBACK 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_NETIF_HWADDRHINT==1: Cache link-layer-address hints (e.g. table
|
||||
* indices) in struct netif. TCP and UDP can make use of this to prevent
|
||||
@@ -1084,14 +1294,14 @@
|
||||
#endif
|
||||
|
||||
/**
|
||||
* PPP_THREAD_NAME: The name assigned to the pppMain thread.
|
||||
* PPP_THREAD_NAME: The name assigned to the pppInputThread.
|
||||
*/
|
||||
#ifndef PPP_THREAD_NAME
|
||||
#define PPP_THREAD_NAME "pppMain"
|
||||
#define PPP_THREAD_NAME "pppInputThread"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* PPP_THREAD_STACKSIZE: The stack size used by the pppMain thread.
|
||||
* PPP_THREAD_STACKSIZE: The stack size used by the pppInputThread.
|
||||
* The stack size value itself is platform-dependent, but is passed to
|
||||
* sys_thread_new() when the thread is created.
|
||||
*/
|
||||
@@ -1100,7 +1310,7 @@
|
||||
#endif
|
||||
|
||||
/**
|
||||
* PPP_THREAD_PRIO: The priority assigned to the pppMain thread.
|
||||
* PPP_THREAD_PRIO: The priority assigned to the pppInputThread.
|
||||
* The priority value itself is platform-dependent, but is passed to
|
||||
* sys_thread_new() when the thread is created.
|
||||
*/
|
||||
@@ -1182,6 +1392,14 @@
|
||||
#define LWIP_TCPIP_CORE_LOCKING 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_TCPIP_CORE_LOCKING_INPUT: (EXPERIMENTAL!)
|
||||
* Don't use it if you're not an active lwIP project member
|
||||
*/
|
||||
#ifndef LWIP_TCPIP_CORE_LOCKING_INPUT
|
||||
#define LWIP_TCPIP_CORE_LOCKING_INPUT 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c)
|
||||
*/
|
||||
@@ -1189,6 +1407,13 @@
|
||||
#define LWIP_NETCONN 1
|
||||
#endif
|
||||
|
||||
/** LWIP_TCPIP_TIMEOUT==1: Enable tcpip_timeout/tcpip_untimeout tod create
|
||||
* timers running in tcpip_thread from another thread.
|
||||
*/
|
||||
#ifndef LWIP_TCPIP_TIMEOUT
|
||||
#define LWIP_TCPIP_TIMEOUT 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
------------------------------------
|
||||
---------- Socket options ----------
|
||||
@@ -1228,7 +1453,16 @@
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_SO_RCVTIMEO==1: Enable SO_RCVTIMEO processing.
|
||||
* LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and
|
||||
* SO_SNDTIMEO processing.
|
||||
*/
|
||||
#ifndef LWIP_SO_SNDTIMEO
|
||||
#define LWIP_SO_SNDTIMEO 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and
|
||||
* SO_RCVTIMEO processing.
|
||||
*/
|
||||
#ifndef LWIP_SO_RCVTIMEO
|
||||
#define LWIP_SO_RCVTIMEO 0
|
||||
@@ -1249,12 +1483,21 @@
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SO_REUSE==1: Enable SO_REUSEADDR and SO_REUSEPORT options. DO NOT USE!
|
||||
* SO_REUSE==1: Enable SO_REUSEADDR option.
|
||||
*/
|
||||
#ifndef SO_REUSE
|
||||
#define SO_REUSE 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SO_REUSE_RXTOALL==1: Pass a copy of incoming broadcast/multicast packets
|
||||
* to all local matches if SO_REUSEADDR is turned on.
|
||||
* WARNING: Adds a memcpy for every packet if passing to more than one pcb!
|
||||
*/
|
||||
#ifndef SO_REUSE_RXTOALL
|
||||
#define SO_REUSE_RXTOALL 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
----------------------------------------
|
||||
---------- Statistics options ----------
|
||||
@@ -1561,6 +1804,13 @@
|
||||
#ifndef CHECKSUM_GEN_TCP
|
||||
#define CHECKSUM_GEN_TCP 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* CHECKSUM_GEN_ICMP==1: Generate checksums in software for outgoing ICMP packets.
|
||||
*/
|
||||
#ifndef CHECKSUM_GEN_ICMP
|
||||
#define CHECKSUM_GEN_ICMP 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.
|
||||
@@ -1583,6 +1833,42 @@
|
||||
#define CHECKSUM_CHECK_TCP 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* LWIP_CHECKSUM_ON_COPY==1: Calculate checksum when copying data from
|
||||
* application buffers to pbufs.
|
||||
*/
|
||||
#ifndef LWIP_CHECKSUM_ON_COPY
|
||||
#define LWIP_CHECKSUM_ON_COPY 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
---------------------------------------
|
||||
---------- Hook options ---------------
|
||||
---------------------------------------
|
||||
*/
|
||||
|
||||
/* Hooks are undefined by default, define them to a function if you need them. */
|
||||
|
||||
/**
|
||||
* LWIP_HOOK_IP4_INPUT(pbuf, input_netif):
|
||||
* - called from ip_input() (IPv4)
|
||||
* - pbuf: received struct pbuf passed to ip_input()
|
||||
* - input_netif: struct netif on which the packet has been received
|
||||
* Return values:
|
||||
* - 0: Hook has not consumed the packet, packet is processed as normal
|
||||
* - != 0: Hook has consumed the packet.
|
||||
* If the hook consumed the packet, 'pbuf' is in the responsibility of the hook
|
||||
* (i.e. free it when done).
|
||||
*/
|
||||
|
||||
/**
|
||||
* LWIP_HOOK_IP4_ROUTE(dest):
|
||||
* - called from ip_route() (IPv4)
|
||||
* - dest: destination IPv4 address
|
||||
* Returns the destination netif or NULL if no destination netif is found. In
|
||||
* that case, ip_route() continues as normal.
|
||||
*/
|
||||
|
||||
/*
|
||||
---------------------------------------
|
||||
---------- Debugging options ----------
|
||||
@@ -1710,6 +1996,13 @@
|
||||
#define SYS_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
/**
|
||||
* TIMERS_DEBUG: Enable debugging in timers.c.
|
||||
*/
|
||||
#ifndef TIMERS_DEBUG
|
||||
#define TIMERS_DEBUG LWIP_DBG_OFF
|
||||
#endif
|
||||
|
||||
/**
|
||||
* TCP_DEBUG: Enable debugging for TCP.
|
||||
*/
|
||||
|
||||
@@ -40,6 +40,10 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Currently, the pbuf_custom code is only needed for one specific configuration
|
||||
* of IP_FRAG */
|
||||
#define LWIP_SUPPORT_CUSTOM_PBUF (IP_FRAG && !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF)
|
||||
|
||||
#define PBUF_TRANSPORT_HLEN 20
|
||||
#define PBUF_IP_HLEN 20
|
||||
|
||||
@@ -59,7 +63,18 @@ typedef enum {
|
||||
|
||||
|
||||
/** indicates this packet's data should be immediately passed to the application */
|
||||
#define PBUF_FLAG_PUSH 0x01U
|
||||
#define PBUF_FLAG_PUSH 0x01U
|
||||
/** indicates this is a custom pbuf: pbuf_free and pbuf_header handle such a
|
||||
a pbuf differently */
|
||||
#define PBUF_FLAG_IS_CUSTOM 0x02U
|
||||
/** indicates this pbuf is UDP multicast to be looped back */
|
||||
#define PBUF_FLAG_MCASTLOOP 0x04U
|
||||
/** indicates this pbuf was received as link-level broadcast */
|
||||
#define PBUF_FLAG_LLBCAST 0x08U
|
||||
/** indicates this pbuf was received as link-level multicast */
|
||||
#define PBUF_FLAG_LLMCAST 0x10U
|
||||
/** indicates this pbuf includes a TCP FIN flag */
|
||||
#define PBUF_FLAG_TCP_FIN 0x20U
|
||||
|
||||
struct pbuf {
|
||||
/** next pbuf in singly linked pbuf chain */
|
||||
@@ -67,7 +82,7 @@ struct pbuf {
|
||||
|
||||
/** pointer to the actual data in the buffer */
|
||||
void *payload;
|
||||
|
||||
|
||||
/**
|
||||
* total length of this buffer and all next buffers in chain
|
||||
* belonging to the same packet.
|
||||
@@ -76,9 +91,9 @@ struct pbuf {
|
||||
* p->tot_len == p->len + (p->next? p->next->tot_len: 0)
|
||||
*/
|
||||
u16_t tot_len;
|
||||
|
||||
|
||||
/** length of this buffer */
|
||||
u16_t len;
|
||||
u16_t len;
|
||||
|
||||
/** pbuf_type as u8_t instead of enum to save space */
|
||||
u8_t /*pbuf_type*/ type;
|
||||
@@ -92,17 +107,51 @@ struct pbuf {
|
||||
* the stack itself, or pbuf->next pointers from a chain.
|
||||
*/
|
||||
u16_t ref;
|
||||
|
||||
};
|
||||
|
||||
#if LWIP_SUPPORT_CUSTOM_PBUF
|
||||
/** Prototype for a function to free a custom pbuf */
|
||||
typedef void (*pbuf_free_custom_fn)(struct pbuf *p);
|
||||
|
||||
/** A custom pbuf: like a pbuf, but following a function pointer to free it. */
|
||||
struct pbuf_custom {
|
||||
/** The actual pbuf */
|
||||
struct pbuf pbuf;
|
||||
/** This function is called when pbuf_free deallocates this pbuf(_custom) */
|
||||
pbuf_free_custom_fn custom_free_function;
|
||||
};
|
||||
#endif /* LWIP_SUPPORT_CUSTOM_PBUF */
|
||||
|
||||
#if LWIP_TCP && TCP_QUEUE_OOSEQ
|
||||
/** Define this to 0 to prevent freeing ooseq pbufs when the PBUF_POOL is empty */
|
||||
#ifndef PBUF_POOL_FREE_OOSEQ
|
||||
#define PBUF_POOL_FREE_OOSEQ 1
|
||||
#endif /* PBUF_POOL_FREE_OOSEQ */
|
||||
#if NO_SYS && PBUF_POOL_FREE_OOSEQ
|
||||
extern volatile u8_t pbuf_free_ooseq_pending;
|
||||
void pbuf_free_ooseq();
|
||||
/** When not using sys_check_timeouts(), call PBUF_CHECK_FREE_OOSEQ()
|
||||
at regular intervals from main level to check if ooseq pbufs need to be
|
||||
freed! */
|
||||
#define PBUF_CHECK_FREE_OOSEQ() do { if(pbuf_free_ooseq_pending) { \
|
||||
/* pbuf_alloc() reported PBUF_POOL to be empty -> try to free some \
|
||||
ooseq queued pbufs now */ \
|
||||
pbuf_free_ooseq(); }}while(0)
|
||||
#endif /* NO_SYS && PBUF_POOL_FREE_OOSEQ*/
|
||||
#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ */
|
||||
|
||||
/* Initializes the pbuf module. This call is empty for now, but may not be in future. */
|
||||
#define pbuf_init()
|
||||
|
||||
struct pbuf *pbuf_alloc(pbuf_layer l, u16_t size, pbuf_type type);
|
||||
struct pbuf *pbuf_alloc(pbuf_layer l, u16_t length, pbuf_type type);
|
||||
#if LWIP_SUPPORT_CUSTOM_PBUF
|
||||
struct pbuf *pbuf_alloced_custom(pbuf_layer l, u16_t length, pbuf_type type,
|
||||
struct pbuf_custom *p, void *payload_mem,
|
||||
u16_t payload_mem_len);
|
||||
#endif /* LWIP_SUPPORT_CUSTOM_PBUF */
|
||||
void pbuf_realloc(struct pbuf *p, u16_t size);
|
||||
u8_t pbuf_header(struct pbuf *p, s16_t header_size);
|
||||
void pbuf_ref(struct pbuf *p);
|
||||
void pbuf_ref_chain(struct pbuf *p);
|
||||
u8_t pbuf_free(struct pbuf *p);
|
||||
u8_t pbuf_clen(struct pbuf *p);
|
||||
void pbuf_cat(struct pbuf *head, struct pbuf *tail);
|
||||
@@ -112,6 +161,15 @@ err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from);
|
||||
u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset);
|
||||
err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len);
|
||||
struct pbuf *pbuf_coalesce(struct pbuf *p, pbuf_layer layer);
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
err_t pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr,
|
||||
u16_t len, u16_t *chksum);
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
|
||||
u8_t pbuf_get_at(struct pbuf* p, u16_t offset);
|
||||
u16_t pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n);
|
||||
u16_t pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset);
|
||||
u16_t pbuf_strstr(struct pbuf* p, const char* substr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
#if LWIP_RAW /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
@@ -45,26 +45,31 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct raw_pcb;
|
||||
|
||||
/** Function prototype for raw pcb receive callback functions.
|
||||
* @param arg user supplied argument (raw_pcb.recv_arg)
|
||||
* @param pcb the raw_pcb which received data
|
||||
* @param p the packet buffer that was received
|
||||
* @param addr the remote IP address from which the packet was received
|
||||
* @return 1 if the packet was 'eaten' (aka. deleted),
|
||||
* 0 if the packet lives on
|
||||
* If returning 1, the callback is responsible for freeing the pbuf
|
||||
* if it's not used any more.
|
||||
*/
|
||||
typedef u8_t (*raw_recv_fn)(void *arg, struct raw_pcb *pcb, struct pbuf *p,
|
||||
ip_addr_t *addr);
|
||||
|
||||
struct raw_pcb {
|
||||
/* Common members of all PCB types */
|
||||
/* Common members of all PCB types */
|
||||
IP_PCB;
|
||||
|
||||
struct raw_pcb *next;
|
||||
|
||||
u8_t protocol;
|
||||
|
||||
/* receive callback function
|
||||
* @param arg user supplied argument (raw_pcb.recv_arg)
|
||||
* @param pcb the raw_pcb which received data
|
||||
* @param p the packet buffer that was received
|
||||
* @param addr the remote IP address from which the packet was received
|
||||
* @return 1 if the packet was 'eaten' (aka. deleted),
|
||||
* 0 if the packet lives on
|
||||
* If returning 1, the callback is responsible for freeing the pbuf
|
||||
* if it's not used any more.
|
||||
*/
|
||||
u8_t (* recv)(void *arg, struct raw_pcb *pcb, struct pbuf *p,
|
||||
struct ip_addr *addr);
|
||||
/** receive callback function */
|
||||
raw_recv_fn recv;
|
||||
/* user-supplied argument for the recv callback */
|
||||
void *recv_arg;
|
||||
};
|
||||
@@ -73,15 +78,11 @@ struct raw_pcb {
|
||||
RAW code. */
|
||||
struct raw_pcb * raw_new (u8_t proto);
|
||||
void raw_remove (struct raw_pcb *pcb);
|
||||
err_t raw_bind (struct raw_pcb *pcb, struct ip_addr *ipaddr);
|
||||
err_t raw_connect (struct raw_pcb *pcb, struct ip_addr *ipaddr);
|
||||
err_t raw_bind (struct raw_pcb *pcb, ip_addr_t *ipaddr);
|
||||
err_t raw_connect (struct raw_pcb *pcb, ip_addr_t *ipaddr);
|
||||
|
||||
void raw_recv (struct raw_pcb *pcb,
|
||||
u8_t (* recv)(void *arg, struct raw_pcb *pcb,
|
||||
struct pbuf *p,
|
||||
struct ip_addr *addr),
|
||||
void *recv_arg);
|
||||
err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr);
|
||||
void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg);
|
||||
err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr);
|
||||
err_t raw_send (struct raw_pcb *pcb, struct pbuf *p);
|
||||
|
||||
/* The following functions are the lower layer interface to RAW. */
|
||||
|
||||
@@ -34,13 +34,16 @@
|
||||
#define __LWIP_SNMP_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/udp.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
struct udp_pcb;
|
||||
struct netif;
|
||||
|
||||
/**
|
||||
* @see RFC1213, "MIB-II, 6. Definitions"
|
||||
*/
|
||||
@@ -118,8 +121,8 @@ void snmp_inc_iflist(void);
|
||||
void snmp_dec_iflist(void);
|
||||
|
||||
/* ARP (for atTable and ipNetToMediaTable) */
|
||||
void snmp_insert_arpidx_tree(struct netif *ni, struct ip_addr *ip);
|
||||
void snmp_delete_arpidx_tree(struct netif *ni, struct ip_addr *ip);
|
||||
void snmp_insert_arpidx_tree(struct netif *ni, ip_addr_t *ip);
|
||||
void snmp_delete_arpidx_tree(struct netif *ni, ip_addr_t *ip);
|
||||
|
||||
/* IP */
|
||||
void snmp_inc_ipinreceives(void);
|
||||
|
||||
@@ -46,12 +46,12 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SNMP_ASN1_UNIV (!0x80 | !0x40)
|
||||
#define SNMP_ASN1_APPLIC (!0x80 | 0x40)
|
||||
#define SNMP_ASN1_CONTXT ( 0x80 | !0x40)
|
||||
#define SNMP_ASN1_UNIV (0) /* (!0x80 | !0x40) */
|
||||
#define SNMP_ASN1_APPLIC (0x40) /* (!0x80 | 0x40) */
|
||||
#define SNMP_ASN1_CONTXT (0x80) /* ( 0x80 | !0x40) */
|
||||
|
||||
#define SNMP_ASN1_CONSTR (0x20)
|
||||
#define SNMP_ASN1_PRIMIT (!0x20)
|
||||
#define SNMP_ASN1_CONSTR (0x20) /* ( 0x20) */
|
||||
#define SNMP_ASN1_PRIMIT (0) /* (!0x20) */
|
||||
|
||||
/* universal tags */
|
||||
#define SNMP_ASN1_INTEG 2
|
||||
@@ -87,10 +87,10 @@ void snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed);
|
||||
void snmp_asn1_enc_oid_cnt(u8_t ident_len, s32_t *ident, u16_t *octets_needed);
|
||||
err_t snmp_asn1_enc_type(struct pbuf *p, u16_t ofs, u8_t type);
|
||||
err_t snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length);
|
||||
err_t snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, u32_t value);
|
||||
err_t snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, s32_t value);
|
||||
err_t snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, u32_t value);
|
||||
err_t snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u16_t octets_needed, s32_t value);
|
||||
err_t snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident);
|
||||
err_t snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u8_t raw_len, u8_t *raw);
|
||||
err_t snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u16_t raw_len, u8_t *raw);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -38,10 +38,14 @@
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/snmp.h"
|
||||
#include "lwip/snmp_structs.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/err.h"
|
||||
|
||||
#if LWIP_SNMP
|
||||
|
||||
#if SNMP_PRIVATE_MIB
|
||||
/* When using a private MIB, you have to create a file 'private_mib.h' that contains
|
||||
* a 'struct mib_array_node mib_private' which contains your MIB. */
|
||||
#include "private_mib.h"
|
||||
#endif
|
||||
|
||||
@@ -219,7 +223,7 @@ struct snmp_msg_pstat
|
||||
/* lwIP local port (161) binding */
|
||||
struct udp_pcb *pcb;
|
||||
/* source IP address */
|
||||
struct ip_addr sip;
|
||||
ip_addr_t sip;
|
||||
/* source UDP port */
|
||||
u16_t sp;
|
||||
/* request type */
|
||||
@@ -258,7 +262,7 @@ struct snmp_msg_trap
|
||||
/* lwIP local port (161) binding */
|
||||
struct udp_pcb *pcb;
|
||||
/* destination IP address in network order */
|
||||
struct ip_addr dip;
|
||||
ip_addr_t dip;
|
||||
|
||||
/* source enterprise ID (sysObjectID) */
|
||||
struct snmp_obj_id *enterprise;
|
||||
@@ -286,7 +290,7 @@ extern struct snmp_msg_trap trap_msg;
|
||||
/** Agent setup, start listening to port 161. */
|
||||
void snmp_init(void);
|
||||
void snmp_trap_dst_enable(u8_t dst_idx, u8_t enable);
|
||||
void snmp_trap_dst_ip_set(u8_t dst_idx, struct ip_addr *dst);
|
||||
void snmp_trap_dst_ip_set(u8_t dst_idx, ip_addr_t *dst);
|
||||
|
||||
/** Varbind-list functions. */
|
||||
struct snmp_varbind* snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len);
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
#include "lwip/snmp.h"
|
||||
|
||||
#if SNMP_PRIVATE_MIB
|
||||
/* When using a private MIB, you have to create a file 'private_mib.h' that contains
|
||||
* a 'struct mib_array_node mib_private' which contains your MIB. */
|
||||
#include "private_mib.h"
|
||||
#endif
|
||||
|
||||
@@ -56,11 +58,15 @@ extern "C" {
|
||||
#define MIB_OBJECT_SCALAR 1
|
||||
#define MIB_OBJECT_TAB 2
|
||||
|
||||
/* MIB access types */
|
||||
#define MIB_ACCESS_READ 1
|
||||
#define MIB_ACCESS_WRITE 2
|
||||
|
||||
/* MIB object access */
|
||||
#define MIB_OBJECT_READ_ONLY 0
|
||||
#define MIB_OBJECT_READ_WRITE 1
|
||||
#define MIB_OBJECT_WRITE_ONLY 2
|
||||
#define MIB_OBJECT_NOT_ACCESSIBLE 3
|
||||
#define MIB_OBJECT_READ_ONLY MIB_ACCESS_READ
|
||||
#define MIB_OBJECT_READ_WRITE (MIB_ACCESS_READ | MIB_ACCESS_WRITE)
|
||||
#define MIB_OBJECT_WRITE_ONLY MIB_ACCESS_WRITE
|
||||
#define MIB_OBJECT_NOT_ACCESSIBLE 0
|
||||
|
||||
/** object definition returned by (get_object_def)() */
|
||||
struct obj_def
|
||||
@@ -109,9 +115,9 @@ struct mib_node
|
||||
/** sets object value, only to be called when set_test() */
|
||||
void (*set_value)(struct obj_def *od, u16_t len, void *value);
|
||||
/** One out of MIB_NODE_AR, MIB_NODE_LR or MIB_NODE_EX */
|
||||
const u8_t node_type;
|
||||
u8_t node_type;
|
||||
/* array or max list length */
|
||||
const u16_t maxlength;
|
||||
u16_t maxlength;
|
||||
};
|
||||
|
||||
/** derived node for scalars .0 index */
|
||||
@@ -122,15 +128,15 @@ typedef struct mib_node mib_scalar_node;
|
||||
struct mib_array_node
|
||||
{
|
||||
/* inherited "base class" members */
|
||||
void (* const get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od);
|
||||
void (* const get_value)(struct obj_def *od, u16_t len, void *value);
|
||||
void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od);
|
||||
void (*get_value)(struct obj_def *od, u16_t len, void *value);
|
||||
u8_t (*set_test)(struct obj_def *od, u16_t len, void *value);
|
||||
void (*set_value)(struct obj_def *od, u16_t len, void *value);
|
||||
|
||||
const u8_t node_type;
|
||||
const u16_t maxlength;
|
||||
u8_t node_type;
|
||||
u16_t maxlength;
|
||||
|
||||
/* aditional struct members */
|
||||
/* additional struct members */
|
||||
const s32_t *objid;
|
||||
struct mib_node* const *nptr;
|
||||
};
|
||||
@@ -174,7 +180,7 @@ struct mib_list_rootnode
|
||||
u8_t node_type;
|
||||
u16_t maxlength;
|
||||
|
||||
/* aditional struct members */
|
||||
/* additional struct members */
|
||||
struct mib_list_node *head;
|
||||
struct mib_list_node *tail;
|
||||
/* counts list nodes in list */
|
||||
@@ -194,8 +200,8 @@ struct mib_external_node
|
||||
u8_t node_type;
|
||||
u16_t maxlength;
|
||||
|
||||
/* aditional struct members */
|
||||
/** points to an extenal (in memory) record of some sort of addressing
|
||||
/* additional struct members */
|
||||
/** points to an external (in memory) record of some sort of addressing
|
||||
information, passed to and interpreted by the funtions below */
|
||||
void* addr_inf;
|
||||
/** tree levels under this node */
|
||||
@@ -234,8 +240,8 @@ void noleafs_get_value(struct obj_def *od, u16_t len, void *value);
|
||||
u8_t noleafs_set_test(struct obj_def *od, u16_t len, void *value);
|
||||
void noleafs_set_value(struct obj_def *od, u16_t len, void *value);
|
||||
|
||||
void snmp_oidtoip(s32_t *ident, struct ip_addr *ip);
|
||||
void snmp_iptooid(struct ip_addr *ip, s32_t *ident);
|
||||
void snmp_oidtoip(s32_t *ident, ip_addr_t *ip);
|
||||
void snmp_iptooid(ip_addr_t *ip, s32_t *ident);
|
||||
void snmp_ifindextonetif(s32_t ifindex, struct netif **netif);
|
||||
void snmp_netiftoifindex(struct netif *netif, s32_t *ifidx);
|
||||
|
||||
|
||||
@@ -62,8 +62,10 @@ struct sockaddr {
|
||||
char sa_data[14];
|
||||
};
|
||||
|
||||
#ifndef socklen_t
|
||||
# define socklen_t u32_t
|
||||
/* If your port already typedef's socklen_t, define SOCKLEN_T_DEFINED
|
||||
to prevent this code from redefining it. */
|
||||
#if !defined(socklen_t) && !defined(SOCKLEN_T_DEFINED)
|
||||
typedef u32_t socklen_t;
|
||||
#endif
|
||||
|
||||
/* Socket protocol types (TCP/UDP/RAW) */
|
||||
@@ -72,11 +74,11 @@ struct sockaddr {
|
||||
#define SOCK_RAW 3
|
||||
|
||||
/*
|
||||
* Option flags per-socket. These must match the SOF_ flags in ip.h!
|
||||
* Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c)
|
||||
*/
|
||||
#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */
|
||||
#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */
|
||||
#define SO_REUSEADDR 0x0004 /* Unimplemented: allow local address reuse */
|
||||
#define SO_REUSEADDR 0x0004 /* Allow local address reuse */
|
||||
#define SO_KEEPALIVE 0x0008 /* keep connections alive */
|
||||
#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */
|
||||
#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */
|
||||
@@ -262,9 +264,27 @@ typedef struct ip_mreq {
|
||||
#define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */
|
||||
#endif
|
||||
|
||||
/* Socket flags: */
|
||||
/* commands for fnctl */
|
||||
#ifndef F_GETFL
|
||||
#define F_GETFL 3
|
||||
#endif
|
||||
#ifndef F_SETFL
|
||||
#define F_SETFL 4
|
||||
#endif
|
||||
|
||||
/* File status flags and file access modes for fnctl,
|
||||
these are bits in an int. */
|
||||
#ifndef O_NONBLOCK
|
||||
#define O_NONBLOCK 04000U
|
||||
#define O_NONBLOCK 1 /* nonblocking I/O */
|
||||
#endif
|
||||
#ifndef O_NDELAY
|
||||
#define O_NDELAY 1 /* same as O_NONBLOCK, for compatibility */
|
||||
#endif
|
||||
|
||||
#ifndef SHUT_RD
|
||||
#define SHUT_RD 0
|
||||
#define SHUT_WR 1
|
||||
#define SHUT_RDWR 2
|
||||
#endif
|
||||
|
||||
/* FD_SET used for lwip_select */
|
||||
@@ -320,6 +340,7 @@ int lwip_write(int s, const void *dataptr, size_t size);
|
||||
int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
|
||||
struct timeval *timeout);
|
||||
int lwip_ioctl(int s, long cmd, void *argp);
|
||||
int lwip_fcntl(int s, int cmd, int val);
|
||||
|
||||
#if LWIP_COMPAT_SOCKETS
|
||||
#define accept(a,b,c) lwip_accept(a,b,c)
|
||||
@@ -344,6 +365,7 @@ int lwip_ioctl(int s, long cmd, void *argp);
|
||||
#define read(a,b,c) lwip_read(a,b,c)
|
||||
#define write(a,b,c) lwip_write(a,b,c)
|
||||
#define close(s) lwip_close(s)
|
||||
#define fcntl(a,b,c) lwip_fcntl(a,b,c)
|
||||
#endif /* LWIP_POSIX_SOCKETS_IO_NAMES */
|
||||
|
||||
#endif /* LWIP_COMPAT_SOCKETS */
|
||||
|
||||
@@ -71,18 +71,26 @@ struct stats_proto {
|
||||
};
|
||||
|
||||
struct stats_igmp {
|
||||
STAT_COUNTER lenerr; /* Invalid length error. */
|
||||
STAT_COUNTER xmit; /* Transmitted packets. */
|
||||
STAT_COUNTER recv; /* Received packets. */
|
||||
STAT_COUNTER drop; /* Dropped packets. */
|
||||
STAT_COUNTER chkerr; /* Checksum error. */
|
||||
STAT_COUNTER v1_rxed; /* */
|
||||
STAT_COUNTER join_sent; /* */
|
||||
STAT_COUNTER leave_sent; /* */
|
||||
STAT_COUNTER unicast_query; /* */
|
||||
STAT_COUNTER report_sent; /* */
|
||||
STAT_COUNTER report_rxed; /* */
|
||||
STAT_COUNTER group_query_rxed; /* */
|
||||
STAT_COUNTER lenerr; /* Invalid length error. */
|
||||
STAT_COUNTER memerr; /* Out of memory error. */
|
||||
STAT_COUNTER proterr; /* Protocol error. */
|
||||
STAT_COUNTER rx_v1; /* Received v1 frames. */
|
||||
STAT_COUNTER rx_group; /* Received group-specific queries. */
|
||||
STAT_COUNTER rx_general; /* Received general queries. */
|
||||
STAT_COUNTER rx_report; /* Received reports. */
|
||||
STAT_COUNTER tx_join; /* Sent joins. */
|
||||
STAT_COUNTER tx_leave; /* Sent leaves. */
|
||||
STAT_COUNTER tx_report; /* Sent reports. */
|
||||
};
|
||||
|
||||
struct stats_mem {
|
||||
#ifdef LWIP_DEBUG
|
||||
const char *name;
|
||||
#endif /* LWIP_DEBUG */
|
||||
mem_size_t avail;
|
||||
mem_size_t used;
|
||||
mem_size_t max;
|
||||
@@ -98,6 +106,7 @@ struct stats_syselem {
|
||||
|
||||
struct stats_sys {
|
||||
struct stats_syselem sem;
|
||||
struct stats_syselem mutex;
|
||||
struct stats_syselem mbox;
|
||||
};
|
||||
|
||||
@@ -139,14 +148,20 @@ struct stats_ {
|
||||
|
||||
extern struct stats_ lwip_stats;
|
||||
|
||||
#define stats_init() /* Compatibility define, not init needed. */
|
||||
void stats_init(void);
|
||||
|
||||
#define STATS_INC(x) ++lwip_stats.x
|
||||
#define STATS_DEC(x) --lwip_stats.x
|
||||
#else
|
||||
#define STATS_INC_USED(x, y) do { lwip_stats.x.used += y; \
|
||||
if (lwip_stats.x.max < lwip_stats.x.used) { \
|
||||
lwip_stats.x.max = lwip_stats.x.used; \
|
||||
} \
|
||||
} while(0)
|
||||
#else /* LWIP_STATS */
|
||||
#define stats_init()
|
||||
#define STATS_INC(x)
|
||||
#define STATS_DEC(x)
|
||||
#define STATS_INC_USED(x)
|
||||
#endif /* LWIP_STATS */
|
||||
|
||||
#if TCP_STATS
|
||||
@@ -216,11 +231,7 @@ extern struct stats_ lwip_stats;
|
||||
#if MEM_STATS
|
||||
#define MEM_STATS_AVAIL(x, y) lwip_stats.mem.x = y
|
||||
#define MEM_STATS_INC(x) STATS_INC(mem.x)
|
||||
#define MEM_STATS_INC_USED(x, y) do { lwip_stats.mem.used += y; \
|
||||
if (lwip_stats.mem.max < lwip_stats.mem.used) { \
|
||||
lwip_stats.mem.max = lwip_stats.mem.used; \
|
||||
} \
|
||||
} while(0)
|
||||
#define MEM_STATS_INC_USED(x, y) STATS_INC_USED(mem, y)
|
||||
#define MEM_STATS_DEC_USED(x, y) lwip_stats.mem.x -= y
|
||||
#define MEM_STATS_DISPLAY() stats_display_mem(&lwip_stats.mem, "HEAP")
|
||||
#else
|
||||
@@ -235,11 +246,7 @@ extern struct stats_ lwip_stats;
|
||||
#define MEMP_STATS_AVAIL(x, i, y) lwip_stats.memp[i].x = y
|
||||
#define MEMP_STATS_INC(x, i) STATS_INC(memp[i].x)
|
||||
#define MEMP_STATS_DEC(x, i) STATS_DEC(memp[i].x)
|
||||
#define MEMP_STATS_INC_USED(x, i) do { ++lwip_stats.memp[i].used; \
|
||||
if (lwip_stats.memp[i].max < lwip_stats.memp[i].used) { \
|
||||
lwip_stats.memp[i].max = lwip_stats.memp[i].used; \
|
||||
} \
|
||||
} while(0)
|
||||
#define MEMP_STATS_INC_USED(x, i) STATS_INC_USED(memp[i], 1)
|
||||
#define MEMP_STATS_DISPLAY(i) stats_display_memp(&lwip_stats.memp[i], i)
|
||||
#else
|
||||
#define MEMP_STATS_AVAIL(x, i, y)
|
||||
@@ -252,22 +259,24 @@ extern struct stats_ lwip_stats;
|
||||
#if SYS_STATS
|
||||
#define SYS_STATS_INC(x) STATS_INC(sys.x)
|
||||
#define SYS_STATS_DEC(x) STATS_DEC(sys.x)
|
||||
#define SYS_STATS_INC_USED(x) STATS_INC_USED(sys.x, 1)
|
||||
#define SYS_STATS_DISPLAY() stats_display_sys(&lwip_stats.sys)
|
||||
#else
|
||||
#define SYS_STATS_INC(x)
|
||||
#define SYS_STATS_DEC(x)
|
||||
#define SYS_STATS_INC_USED(x)
|
||||
#define SYS_STATS_DISPLAY()
|
||||
#endif
|
||||
|
||||
/* Display of statistics */
|
||||
#if LWIP_STATS_DISPLAY
|
||||
void stats_display(void);
|
||||
void stats_display_proto(struct stats_proto *proto, char *name);
|
||||
void stats_display_proto(struct stats_proto *proto, const char *name);
|
||||
void stats_display_igmp(struct stats_igmp *igmp);
|
||||
void stats_display_mem(struct stats_mem *mem, char *name);
|
||||
void stats_display_mem(struct stats_mem *mem, const char *name);
|
||||
void stats_display_memp(struct stats_mem *mem, int index);
|
||||
void stats_display_sys(struct stats_sys *sys);
|
||||
#else
|
||||
#else /* LWIP_STATS_DISPLAY */
|
||||
#define stats_display()
|
||||
#define stats_display_proto(proto, name)
|
||||
#define stats_display_igmp(igmp)
|
||||
|
||||
@@ -43,33 +43,41 @@ extern "C" {
|
||||
/* For a totally minimal and standalone system, we provide null
|
||||
definitions of the sys_ functions. */
|
||||
typedef u8_t sys_sem_t;
|
||||
typedef u8_t sys_mutex_t;
|
||||
typedef u8_t sys_mbox_t;
|
||||
struct sys_timeo {u8_t dummy;};
|
||||
|
||||
#define sys_init()
|
||||
#define sys_timeout(m,h,a)
|
||||
#define sys_untimeout(m,a)
|
||||
#define sys_sem_new(c) c
|
||||
#define sys_sem_new(s, c) ERR_OK
|
||||
#define sys_sem_signal(s)
|
||||
#define sys_sem_wait(s)
|
||||
#define sys_sem_wait_timeout(s,t)
|
||||
#define sys_arch_sem_wait(s,t)
|
||||
#define sys_sem_free(s)
|
||||
#define sys_mbox_new(s) 0
|
||||
#define sys_sem_valid(s) 0
|
||||
#define sys_sem_set_invalid(s)
|
||||
#define sys_mutex_new(mu) ERR_OK
|
||||
#define sys_mutex_lock(mu)
|
||||
#define sys_mutex_unlock(mu)
|
||||
#define sys_mutex_free(mu)
|
||||
#define sys_mutex_valid(mu) 0
|
||||
#define sys_mutex_set_invalid(mu)
|
||||
#define sys_mbox_new(m, s) ERR_OK
|
||||
#define sys_mbox_fetch(m,d)
|
||||
#define sys_mbox_tryfetch(m,d)
|
||||
#define sys_mbox_post(m,d)
|
||||
#define sys_mbox_trypost(m,d)
|
||||
#define sys_mbox_free(m)
|
||||
#define sys_mbox_valid(m)
|
||||
#define sys_mbox_set_invalid(m)
|
||||
|
||||
#define sys_thread_new(n,t,a,s,p)
|
||||
|
||||
#define sys_msleep(t)
|
||||
|
||||
#else /* NO_SYS */
|
||||
|
||||
/** Return code for timeouts from sys_arch_mbox_fetch and sys_arch_sem_wait */
|
||||
#define SYS_ARCH_TIMEOUT 0xffffffffUL
|
||||
|
||||
/* sys_mbox_tryfetch returns SYS_MBOX_EMPTY if appropriate.
|
||||
/** sys_mbox_tryfetch() returns SYS_MBOX_EMPTY if appropriate.
|
||||
* For now we use the same magic value, but we allow this to change in future.
|
||||
*/
|
||||
#define SYS_MBOX_EMPTY SYS_ARCH_TIMEOUT
|
||||
@@ -77,70 +85,156 @@ struct sys_timeo {u8_t dummy;};
|
||||
#include "lwip/err.h"
|
||||
#include "arch/sys_arch.h"
|
||||
|
||||
typedef void (* sys_timeout_handler)(void *arg);
|
||||
/** Function prototype for thread functions */
|
||||
typedef void (*lwip_thread_fn)(void *arg);
|
||||
|
||||
struct sys_timeo {
|
||||
struct sys_timeo *next;
|
||||
u32_t time;
|
||||
sys_timeout_handler h;
|
||||
void *arg;
|
||||
};
|
||||
/* Function prototypes for functions to be implemented by platform ports
|
||||
(in sys_arch.c) */
|
||||
|
||||
struct sys_timeouts {
|
||||
struct sys_timeo *next;
|
||||
};
|
||||
/* Mutex functions: */
|
||||
|
||||
/* sys_init() must be called before anthing else. */
|
||||
void sys_init(void);
|
||||
/** Define LWIP_COMPAT_MUTEX if the port has no mutexes and binary semaphores
|
||||
should be used instead */
|
||||
#if LWIP_COMPAT_MUTEX
|
||||
/* for old ports that don't have mutexes: define them to binary semaphores */
|
||||
#define sys_mutex_t sys_sem_t
|
||||
#define sys_mutex_new(mutex) sys_sem_new(mutex, 1)
|
||||
#define sys_mutex_lock(mutex) sys_sem_wait(mutex)
|
||||
#define sys_mutex_unlock(mutex) sys_sem_signal(mutex)
|
||||
#define sys_mutex_free(mutex) sys_sem_free(mutex)
|
||||
#define sys_mutex_valid(mutex) sys_sem_valid(mutex)
|
||||
#define sys_mutex_set_invalid(mutex) sys_sem_set_invalid(mutex)
|
||||
|
||||
/*
|
||||
* sys_timeout():
|
||||
*
|
||||
* Schedule a timeout a specified amount of milliseconds in the
|
||||
* future. When the timeout occurs, the specified timeout handler will
|
||||
* be called. The handler will be passed the "arg" argument when
|
||||
* called.
|
||||
*
|
||||
*/
|
||||
void sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg);
|
||||
void sys_untimeout(sys_timeout_handler h, void *arg);
|
||||
struct sys_timeouts *sys_arch_timeouts(void);
|
||||
#else /* LWIP_COMPAT_MUTEX */
|
||||
|
||||
/* Semaphore functions. */
|
||||
sys_sem_t sys_sem_new(u8_t count);
|
||||
void sys_sem_signal(sys_sem_t sem);
|
||||
u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout);
|
||||
void sys_sem_free(sys_sem_t sem);
|
||||
void sys_sem_wait(sys_sem_t sem);
|
||||
int sys_sem_wait_timeout(sys_sem_t sem, u32_t timeout);
|
||||
/** Create a new mutex
|
||||
* @param mutex pointer to the mutex to create
|
||||
* @return a new mutex */
|
||||
err_t sys_mutex_new(sys_mutex_t *mutex);
|
||||
/** Lock a mutex
|
||||
* @param mutex the mutex to lock */
|
||||
void sys_mutex_lock(sys_mutex_t *mutex);
|
||||
/** Unlock a mutex
|
||||
* @param mutex the mutex to unlock */
|
||||
void sys_mutex_unlock(sys_mutex_t *mutex);
|
||||
/** Delete a semaphore
|
||||
* @param mutex the mutex to delete */
|
||||
void sys_mutex_free(sys_mutex_t *mutex);
|
||||
#ifndef sys_mutex_valid
|
||||
/** Check if a mutex is valid/allocated: return 1 for valid, 0 for invalid */
|
||||
int sys_mutex_valid(sys_mutex_t *mutex);
|
||||
#endif
|
||||
#ifndef sys_mutex_set_invalid
|
||||
/** Set a mutex invalid so that sys_mutex_valid returns 0 */
|
||||
void sys_mutex_set_invalid(sys_mutex_t *mutex);
|
||||
#endif
|
||||
#endif /* LWIP_COMPAT_MUTEX */
|
||||
|
||||
/* Semaphore functions: */
|
||||
|
||||
/** Create a new semaphore
|
||||
* @param sem pointer to the semaphore to create
|
||||
* @param count initial count of the semaphore
|
||||
* @return ERR_OK if successful, another err_t otherwise */
|
||||
err_t sys_sem_new(sys_sem_t *sem, u8_t count);
|
||||
/** Signals a semaphore
|
||||
* @param sem the semaphore to signal */
|
||||
void sys_sem_signal(sys_sem_t *sem);
|
||||
/** Wait for a semaphore for the specified timeout
|
||||
* @param sem the semaphore to wait for
|
||||
* @param timeout timeout in milliseconds to wait (0 = wait forever)
|
||||
* @return time (in milliseconds) waited for the semaphore
|
||||
* or SYS_ARCH_TIMEOUT on timeout */
|
||||
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout);
|
||||
/** Delete a semaphore
|
||||
* @param sem semaphore to delete */
|
||||
void sys_sem_free(sys_sem_t *sem);
|
||||
/** Wait for a semaphore - forever/no timeout */
|
||||
#define sys_sem_wait(sem) sys_arch_sem_wait(sem, 0)
|
||||
#ifndef sys_sem_valid
|
||||
/** Check if a sempahore is valid/allocated: return 1 for valid, 0 for invalid */
|
||||
int sys_sem_valid(sys_sem_t *sem);
|
||||
#endif
|
||||
#ifndef sys_sem_set_invalid
|
||||
/** Set a semaphore invalid so that sys_sem_valid returns 0 */
|
||||
void sys_sem_set_invalid(sys_sem_t *sem);
|
||||
#endif
|
||||
|
||||
/* Time functions. */
|
||||
#ifndef sys_msleep
|
||||
void sys_msleep(u32_t ms); /* only has a (close to) 1 jiffy resolution. */
|
||||
#endif
|
||||
#ifndef sys_jiffies
|
||||
u32_t sys_jiffies(void); /* since power up. */
|
||||
#endif
|
||||
|
||||
/* Mailbox functions. */
|
||||
sys_mbox_t sys_mbox_new(int size);
|
||||
void sys_mbox_post(sys_mbox_t mbox, void *msg);
|
||||
err_t sys_mbox_trypost(sys_mbox_t mbox, void *msg);
|
||||
u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout);
|
||||
#ifndef sys_arch_mbox_tryfetch /* Allow port to override with a macro */
|
||||
u32_t sys_arch_mbox_tryfetch(sys_mbox_t mbox, void **msg);
|
||||
#endif
|
||||
/* For now, we map straight to sys_arch implementation. */
|
||||
#define sys_mbox_tryfetch(mbox, msg) sys_arch_mbox_tryfetch(mbox, msg)
|
||||
void sys_mbox_free(sys_mbox_t mbox);
|
||||
void sys_mbox_fetch(sys_mbox_t mbox, void **msg);
|
||||
|
||||
/* Thread functions. */
|
||||
sys_thread_t sys_thread_new(char *name, void (* thread)(void *arg), void *arg, int stacksize, int prio);
|
||||
/** Create a new mbox of specified size
|
||||
* @param mbox pointer to the mbox to create
|
||||
* @param size (miminum) number of messages in this mbox
|
||||
* @return ERR_OK if successful, another err_t otherwise */
|
||||
err_t sys_mbox_new(sys_mbox_t *mbox, int size);
|
||||
/** Post a message to an mbox - may not fail
|
||||
* -> blocks if full, only used from tasks not from ISR
|
||||
* @param mbox mbox to posts the message
|
||||
* @param msg message to post (ATTENTION: can be NULL) */
|
||||
void sys_mbox_post(sys_mbox_t *mbox, void *msg);
|
||||
/** Try to post a message to an mbox - may fail if full or ISR
|
||||
* @param mbox mbox to posts the message
|
||||
* @param msg message to post (ATTENTION: can be NULL) */
|
||||
err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg);
|
||||
/** Wait for a new message to arrive in the mbox
|
||||
* @param mbox mbox to get a message from
|
||||
* @param msg pointer where the message is stored
|
||||
* @param timeout maximum time (in milliseconds) to wait for a message
|
||||
* @return time (in milliseconds) waited for a message, may be 0 if not waited
|
||||
or SYS_ARCH_TIMEOUT on timeout
|
||||
* The returned time has to be accurate to prevent timer jitter! */
|
||||
u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout);
|
||||
/* Allow port to override with a macro, e.g. special timout for sys_arch_mbox_fetch() */
|
||||
#ifndef sys_arch_mbox_tryfetch
|
||||
/** Wait for a new message to arrive in the mbox
|
||||
* @param mbox mbox to get a message from
|
||||
* @param msg pointer where the message is stored
|
||||
* @param timeout maximum time (in milliseconds) to wait for a message
|
||||
* @return 0 (milliseconds) if a message has been received
|
||||
* or SYS_MBOX_EMPTY if the mailbox is empty */
|
||||
u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg);
|
||||
#endif
|
||||
/** For now, we map straight to sys_arch implementation. */
|
||||
#define sys_mbox_tryfetch(mbox, msg) sys_arch_mbox_tryfetch(mbox, msg)
|
||||
/** Delete an mbox
|
||||
* @param mbox mbox to delete */
|
||||
void sys_mbox_free(sys_mbox_t *mbox);
|
||||
#define sys_mbox_fetch(mbox, msg) sys_arch_mbox_fetch(mbox, msg, 0)
|
||||
#ifndef sys_mbox_valid
|
||||
/** Check if an mbox is valid/allocated: return 1 for valid, 0 for invalid */
|
||||
int sys_mbox_valid(sys_mbox_t *mbox);
|
||||
#endif
|
||||
#ifndef sys_mbox_set_invalid
|
||||
/** Set an mbox invalid so that sys_mbox_valid returns 0 */
|
||||
void sys_mbox_set_invalid(sys_mbox_t *mbox);
|
||||
#endif
|
||||
|
||||
/** The only thread function:
|
||||
* Creates a new thread
|
||||
* @param name human-readable name for the thread (used for debugging purposes)
|
||||
* @param thread thread-function
|
||||
* @param arg parameter passed to 'thread'
|
||||
* @param stacksize stack size in bytes for the new thread (may be ignored by ports)
|
||||
* @param prio priority of the new thread (may be ignored by ports) */
|
||||
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio);
|
||||
|
||||
#endif /* NO_SYS */
|
||||
|
||||
/** Returns the current time in milliseconds. */
|
||||
/* sys_init() must be called before anthing else. */
|
||||
void sys_init(void);
|
||||
|
||||
#ifndef sys_jiffies
|
||||
/** Ticks/jiffies since power up. */
|
||||
u32_t sys_jiffies(void);
|
||||
#endif
|
||||
|
||||
/** Returns the current time in milliseconds,
|
||||
* may be the same as sys_jiffies or at least based on it. */
|
||||
u32_t sys_now(void);
|
||||
|
||||
/* Critical Region Protection */
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
|
||||
#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip.h"
|
||||
@@ -49,198 +48,80 @@ extern "C" {
|
||||
|
||||
struct tcp_pcb;
|
||||
|
||||
/* Functions for interfacing with TCP: */
|
||||
|
||||
/* Lower layer interface to TCP: */
|
||||
#define tcp_init() /* Compatibility define, not init needed. */
|
||||
void tcp_tmr (void); /* Must be called every
|
||||
TCP_TMR_INTERVAL
|
||||
ms. (Typically 250 ms). */
|
||||
/* Application program's interface: */
|
||||
struct tcp_pcb * tcp_new (void);
|
||||
struct tcp_pcb * tcp_alloc (u8_t prio);
|
||||
|
||||
void tcp_arg (struct tcp_pcb *pcb, void *arg);
|
||||
void tcp_accept (struct tcp_pcb *pcb,
|
||||
err_t (* accept)(void *arg, struct tcp_pcb *newpcb,
|
||||
err_t err));
|
||||
void tcp_recv (struct tcp_pcb *pcb,
|
||||
err_t (* recv)(void *arg, struct tcp_pcb *tpcb,
|
||||
struct pbuf *p, err_t err));
|
||||
void tcp_sent (struct tcp_pcb *pcb,
|
||||
err_t (* sent)(void *arg, struct tcp_pcb *tpcb,
|
||||
u16_t len));
|
||||
void tcp_poll (struct tcp_pcb *pcb,
|
||||
err_t (* poll)(void *arg, struct tcp_pcb *tpcb),
|
||||
u8_t interval);
|
||||
void tcp_err (struct tcp_pcb *pcb,
|
||||
void (* err)(void *arg, err_t err));
|
||||
|
||||
#define tcp_mss(pcb) ((pcb)->mss)
|
||||
#define tcp_sndbuf(pcb) ((pcb)->snd_buf)
|
||||
#define tcp_nagle_disable(pcb) ((pcb)->flags |= TF_NODELAY)
|
||||
#define tcp_nagle_enable(pcb) ((pcb)->flags &= ~TF_NODELAY)
|
||||
#define tcp_nagle_disabled(pcb) (((pcb)->flags & TF_NODELAY) != 0)
|
||||
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
#define tcp_accepted(pcb) (((struct tcp_pcb_listen *)(pcb))->accepts_pending--)
|
||||
#else /* TCP_LISTEN_BACKLOG */
|
||||
#define tcp_accepted(pcb)
|
||||
#endif /* TCP_LISTEN_BACKLOG */
|
||||
|
||||
void tcp_recved (struct tcp_pcb *pcb, u16_t len);
|
||||
err_t tcp_bind (struct tcp_pcb *pcb, struct ip_addr *ipaddr,
|
||||
u16_t port);
|
||||
err_t tcp_connect (struct tcp_pcb *pcb, struct ip_addr *ipaddr,
|
||||
u16_t port, err_t (* connected)(void *arg,
|
||||
struct tcp_pcb *tpcb,
|
||||
err_t err));
|
||||
|
||||
struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog);
|
||||
#define tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG)
|
||||
|
||||
void tcp_abandon (struct tcp_pcb *pcb, int reset);
|
||||
#define tcp_abort(pcb) tcp_abandon((pcb), 1)
|
||||
err_t tcp_close (struct tcp_pcb *pcb);
|
||||
|
||||
/* Flags for "apiflags" parameter in tcp_write and tcp_enqueue */
|
||||
#define TCP_WRITE_FLAG_COPY 0x01
|
||||
#define TCP_WRITE_FLAG_MORE 0x02
|
||||
|
||||
err_t tcp_write (struct tcp_pcb *pcb, const void *dataptr, u16_t len,
|
||||
u8_t apiflags);
|
||||
|
||||
void tcp_setprio (struct tcp_pcb *pcb, u8_t prio);
|
||||
|
||||
#define TCP_PRIO_MIN 1
|
||||
#define TCP_PRIO_NORMAL 64
|
||||
#define TCP_PRIO_MAX 127
|
||||
|
||||
/* It is also possible to call these two functions at the right
|
||||
intervals (instead of calling tcp_tmr()). */
|
||||
void tcp_slowtmr (void);
|
||||
void tcp_fasttmr (void);
|
||||
|
||||
|
||||
/* Only used by IP to pass a TCP segment to TCP: */
|
||||
void tcp_input (struct pbuf *p, struct netif *inp);
|
||||
/* Used within the TCP code only: */
|
||||
err_t tcp_send_empty_ack(struct tcp_pcb *pcb);
|
||||
err_t tcp_output (struct tcp_pcb *pcb);
|
||||
void tcp_rexmit (struct tcp_pcb *pcb);
|
||||
void tcp_rexmit_rto (struct tcp_pcb *pcb);
|
||||
void tcp_rexmit_fast (struct tcp_pcb *pcb);
|
||||
u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb);
|
||||
|
||||
/**
|
||||
* This is the Nagle algorithm: try to combine user data to send as few TCP
|
||||
* segments as possible. Only send if
|
||||
* - no previously transmitted data on the connection remains unacknowledged or
|
||||
* - the TF_NODELAY flag is set (nagle algorithm turned off for this pcb) or
|
||||
* - the only unsent segment is at least pcb->mss bytes long (or there is more
|
||||
* than one unsent segment - with lwIP, this can happen although unsent->len < mss)
|
||||
* - or if we are in fast-retransmit (TF_INFR)
|
||||
/** Function prototype for tcp accept callback functions. Called when a new
|
||||
* connection can be accepted on a listening pcb.
|
||||
*
|
||||
* @param arg Additional argument to pass to the callback function (@see tcp_arg())
|
||||
* @param newpcb The new connection pcb
|
||||
* @param err An error code if there has been an error accepting.
|
||||
* Only return ERR_ABRT if you have called tcp_abort from within the
|
||||
* callback function!
|
||||
*/
|
||||
#define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \
|
||||
((tpcb)->flags & (TF_NODELAY | TF_INFR)) || \
|
||||
(((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \
|
||||
((tpcb)->unsent->len >= (tpcb)->mss))) \
|
||||
) ? 1 : 0)
|
||||
#define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK)
|
||||
typedef err_t (*tcp_accept_fn)(void *arg, struct tcp_pcb *newpcb, err_t err);
|
||||
|
||||
|
||||
#define TCP_SEQ_LT(a,b) ((s32_t)((a)-(b)) < 0)
|
||||
#define TCP_SEQ_LEQ(a,b) ((s32_t)((a)-(b)) <= 0)
|
||||
#define TCP_SEQ_GT(a,b) ((s32_t)((a)-(b)) > 0)
|
||||
#define TCP_SEQ_GEQ(a,b) ((s32_t)((a)-(b)) >= 0)
|
||||
/* is b<=a<=c? */
|
||||
#if 0 /* see bug #10548 */
|
||||
#define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b))
|
||||
#endif
|
||||
#define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c))
|
||||
#define TCP_FIN 0x01U
|
||||
#define TCP_SYN 0x02U
|
||||
#define TCP_RST 0x04U
|
||||
#define TCP_PSH 0x08U
|
||||
#define TCP_ACK 0x10U
|
||||
#define TCP_URG 0x20U
|
||||
#define TCP_ECE 0x40U
|
||||
#define TCP_CWR 0x80U
|
||||
|
||||
#define TCP_FLAGS 0x3fU
|
||||
|
||||
/* Length of the TCP header, excluding options. */
|
||||
#define TCP_HLEN 20
|
||||
|
||||
#ifndef TCP_TMR_INTERVAL
|
||||
#define TCP_TMR_INTERVAL 250 /* The TCP timer interval in milliseconds. */
|
||||
#endif /* TCP_TMR_INTERVAL */
|
||||
|
||||
#ifndef TCP_FAST_INTERVAL
|
||||
#define TCP_FAST_INTERVAL TCP_TMR_INTERVAL /* the fine grained timeout in milliseconds */
|
||||
#endif /* TCP_FAST_INTERVAL */
|
||||
|
||||
#ifndef TCP_SLOW_INTERVAL
|
||||
#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) /* the coarse grained timeout in milliseconds */
|
||||
#endif /* TCP_SLOW_INTERVAL */
|
||||
|
||||
#define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */
|
||||
#define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */
|
||||
|
||||
#define TCP_OOSEQ_TIMEOUT 6U /* x RTO */
|
||||
|
||||
#ifndef TCP_MSL
|
||||
#define TCP_MSL 60000UL /* The maximum segment lifetime in milliseconds */
|
||||
#endif
|
||||
|
||||
/* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */
|
||||
#ifndef TCP_KEEPIDLE_DEFAULT
|
||||
#define TCP_KEEPIDLE_DEFAULT 7200000UL /* Default KEEPALIVE timer in milliseconds */
|
||||
#endif
|
||||
|
||||
#ifndef TCP_KEEPINTVL_DEFAULT
|
||||
#define TCP_KEEPINTVL_DEFAULT 75000UL /* Default Time between KEEPALIVE probes in milliseconds */
|
||||
#endif
|
||||
|
||||
#ifndef TCP_KEEPCNT_DEFAULT
|
||||
#define TCP_KEEPCNT_DEFAULT 9U /* Default Counter for KEEPALIVE probes */
|
||||
#endif
|
||||
|
||||
#define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT /* Maximum KEEPALIVE probe time */
|
||||
|
||||
/* Fields are (of course) in network byte order.
|
||||
* Some fields are converted to host byte order in tcp_input().
|
||||
/** Function prototype for tcp receive callback functions. Called when data has
|
||||
* been received.
|
||||
*
|
||||
* @param arg Additional argument to pass to the callback function (@see tcp_arg())
|
||||
* @param tpcb The connection pcb which received data
|
||||
* @param p The received data (or NULL when the connection has been closed!)
|
||||
* @param err An error code if there has been an error receiving
|
||||
* Only return ERR_ABRT if you have called tcp_abort from within the
|
||||
* callback function!
|
||||
*/
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct tcp_hdr {
|
||||
PACK_STRUCT_FIELD(u16_t src);
|
||||
PACK_STRUCT_FIELD(u16_t dest);
|
||||
PACK_STRUCT_FIELD(u32_t seqno);
|
||||
PACK_STRUCT_FIELD(u32_t ackno);
|
||||
PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags);
|
||||
PACK_STRUCT_FIELD(u16_t wnd);
|
||||
PACK_STRUCT_FIELD(u16_t chksum);
|
||||
PACK_STRUCT_FIELD(u16_t urgp);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
typedef err_t (*tcp_recv_fn)(void *arg, struct tcp_pcb *tpcb,
|
||||
struct pbuf *p, err_t err);
|
||||
|
||||
#define TCPH_OFFSET(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 8)
|
||||
#define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12)
|
||||
#define TCPH_FLAGS(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)
|
||||
/** Function prototype for tcp sent callback functions. Called when sent data has
|
||||
* been acknowledged by the remote side. Use it to free corresponding resources.
|
||||
* This also means that the pcb has now space available to send new data.
|
||||
*
|
||||
* @param arg Additional argument to pass to the callback function (@see tcp_arg())
|
||||
* @param tpcb The connection pcb for which data has been acknowledged
|
||||
* @param len The amount of bytes acknowledged
|
||||
* @return ERR_OK: try to send some data by calling tcp_output
|
||||
* Only return ERR_ABRT if you have called tcp_abort from within the
|
||||
* callback function!
|
||||
*/
|
||||
typedef err_t (*tcp_sent_fn)(void *arg, struct tcp_pcb *tpcb,
|
||||
u16_t len);
|
||||
|
||||
#define TCPH_OFFSET_SET(phdr, offset) (phdr)->_hdrlen_rsvd_flags = htons(((offset) << 8) | TCPH_FLAGS(phdr))
|
||||
#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr))
|
||||
#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & htons((u16_t)(~(u16_t)(TCP_FLAGS)))) | htons(flags))
|
||||
#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | htons(flags))
|
||||
#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) )
|
||||
/** Function prototype for tcp poll callback functions. Called periodically as
|
||||
* specified by @see tcp_poll.
|
||||
*
|
||||
* @param arg Additional argument to pass to the callback function (@see tcp_arg())
|
||||
* @param tpcb tcp pcb
|
||||
* @return ERR_OK: try to send some data by calling tcp_output
|
||||
* Only return ERR_ABRT if you have called tcp_abort from within the
|
||||
* callback function!
|
||||
*/
|
||||
typedef err_t (*tcp_poll_fn)(void *arg, struct tcp_pcb *tpcb);
|
||||
|
||||
#define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0))
|
||||
/** Function prototype for tcp error callback functions. Called when the pcb
|
||||
* receives a RST or is unexpectedly closed for any other reason.
|
||||
*
|
||||
* @note The corresponding pcb is already freed when this callback is called!
|
||||
*
|
||||
* @param arg Additional argument to pass to the callback function (@see tcp_arg())
|
||||
* @param err Error code to indicate why the pcb has been closed
|
||||
* ERR_ABRT: aborted through tcp_abort or by a TCP timer
|
||||
* ERR_RST: the connection was reset by the remote host
|
||||
*/
|
||||
typedef void (*tcp_err_fn)(void *arg, err_t err);
|
||||
|
||||
/** Function prototype for tcp connected callback functions. Called when a pcb
|
||||
* is connected to the remote side after initiating a connection attempt by
|
||||
* calling tcp_connect().
|
||||
*
|
||||
* @param arg Additional argument to pass to the callback function (@see tcp_arg())
|
||||
* @param tpcb The connection pcb which is connected
|
||||
* @param err An unused error code, always ERR_OK currently ;-) TODO!
|
||||
* Only return ERR_ABRT if you have called tcp_abort from within the
|
||||
* callback function!
|
||||
*
|
||||
* @note When a connection attempt fails, the error callback is currently called!
|
||||
*/
|
||||
typedef err_t (*tcp_connected_fn)(void *arg, struct tcp_pcb *tpcb, err_t err);
|
||||
|
||||
enum tcp_state {
|
||||
CLOSED = 0,
|
||||
@@ -256,13 +137,6 @@ enum tcp_state {
|
||||
TIME_WAIT = 10
|
||||
};
|
||||
|
||||
/** Flags used on input processing, not on pcb->flags
|
||||
*/
|
||||
#define TF_RESET (u8_t)0x08U /* Connection was reset. */
|
||||
#define TF_CLOSED (u8_t)0x10U /* Connection was sucessfully closed. */
|
||||
#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */
|
||||
|
||||
|
||||
#if LWIP_CALLBACK_API
|
||||
/* Function to call when a listener has been connected.
|
||||
* @param arg user-supplied argument (tcp_pcb.callback_arg)
|
||||
@@ -271,7 +145,7 @@ enum tcp_state {
|
||||
* @return ERR_OK: accept the new connection,
|
||||
* any other err_t abortsthe new connection
|
||||
*/
|
||||
#define DEF_ACCEPT_CALLBACK err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err)
|
||||
#define DEF_ACCEPT_CALLBACK tcp_accept_fn accept;
|
||||
#else /* LWIP_CALLBACK_API */
|
||||
#define DEF_ACCEPT_CALLBACK
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
@@ -281,13 +155,13 @@ enum tcp_state {
|
||||
*/
|
||||
#define TCP_PCB_COMMON(type) \
|
||||
type *next; /* for the linked list */ \
|
||||
void *callback_arg; \
|
||||
/* the accept callback for listen- and normal pcbs, if LWIP_CALLBACK_API */ \
|
||||
DEF_ACCEPT_CALLBACK \
|
||||
enum tcp_state state; /* TCP state */ \
|
||||
u8_t prio; \
|
||||
void *callback_arg; \
|
||||
/* ports are in host byte order */ \
|
||||
u16_t local_port; \
|
||||
/* the accept callback for listen- and normal pcbs, if LWIP_CALLBACK_API */ \
|
||||
DEF_ACCEPT_CALLBACK
|
||||
u16_t local_port
|
||||
|
||||
|
||||
/* the TCP protocol control block */
|
||||
@@ -305,27 +179,30 @@ struct tcp_pcb {
|
||||
#define TF_ACK_NOW ((u8_t)0x02U) /* Immediate ACK. */
|
||||
#define TF_INFR ((u8_t)0x04U) /* In fast recovery. */
|
||||
#define TF_TIMESTAMP ((u8_t)0x08U) /* Timestamp option enabled */
|
||||
#define TF_RXCLOSED ((u8_t)0x10U) /* rx closed by tcp_shutdown */
|
||||
#define TF_FIN ((u8_t)0x20U) /* Connection was closed locally (FIN segment enqueued). */
|
||||
#define TF_NODELAY ((u8_t)0x40U) /* Disable Nagle algorithm */
|
||||
#define TF_NAGLEMEMERR ((u8_t)0x80U) /* nagle enabled, memerr, try to output to prevent delayed ACK to happen */
|
||||
|
||||
/* the rest of the fields are in host byte order
|
||||
as we have to do some math with them */
|
||||
|
||||
/* Timers */
|
||||
u8_t polltmr, pollinterval;
|
||||
u8_t last_timer;
|
||||
u32_t tmr;
|
||||
|
||||
/* receiver variables */
|
||||
u32_t rcv_nxt; /* next seqno expected */
|
||||
u16_t rcv_wnd; /* receiver window available */
|
||||
u16_t rcv_ann_wnd; /* receiver window to announce */
|
||||
u32_t rcv_ann_right_edge; /* announced right edge of window */
|
||||
|
||||
/* Timers */
|
||||
u32_t tmr;
|
||||
u8_t polltmr, pollinterval;
|
||||
|
||||
/* Retransmission timer. */
|
||||
s16_t rtime;
|
||||
|
||||
|
||||
u16_t mss; /* maximum segment size */
|
||||
|
||||
|
||||
/* RTT (round trip time) estimation variables */
|
||||
u32_t rttest; /* RTT estimate in 500ms ticks */
|
||||
u32_t rtseq; /* sequence number being timed */
|
||||
@@ -335,27 +212,32 @@ struct tcp_pcb {
|
||||
u8_t nrtx; /* number of retransmissions */
|
||||
|
||||
/* fast retransmit/recovery */
|
||||
u32_t lastack; /* Highest acknowledged seqno. */
|
||||
u8_t dupacks;
|
||||
|
||||
u32_t lastack; /* Highest acknowledged seqno. */
|
||||
|
||||
/* congestion avoidance/control variables */
|
||||
u16_t cwnd;
|
||||
u16_t cwnd;
|
||||
u16_t ssthresh;
|
||||
|
||||
/* sender variables */
|
||||
u32_t snd_nxt; /* next new seqno to be sent */
|
||||
u16_t snd_wnd; /* sender window */
|
||||
u32_t snd_wl1, snd_wl2; /* Sequence and acknowledgement numbers of last
|
||||
window update. */
|
||||
u32_t snd_lbb; /* Sequence number of next byte to be buffered. */
|
||||
u16_t snd_wnd; /* sender window */
|
||||
u16_t snd_wnd_max; /* the maximum sender window announced by the remote host */
|
||||
|
||||
u16_t acked;
|
||||
|
||||
|
||||
u16_t snd_buf; /* Available buffer space for sending (in bytes). */
|
||||
#define TCP_SNDQUEUELEN_OVERFLOW (0xffff-3)
|
||||
#define TCP_SNDQUEUELEN_OVERFLOW (0xffffU-3)
|
||||
u16_t snd_queuelen; /* Available buffer space for sending (in tcp_segs). */
|
||||
|
||||
|
||||
|
||||
#if TCP_OVERSIZE
|
||||
/* Extra bytes available at the end of the last pbuf in unsent. */
|
||||
u16_t unsent_oversize;
|
||||
#endif /* TCP_OVERSIZE */
|
||||
|
||||
/* These are ordered by sequence number: */
|
||||
struct tcp_seg *unsent; /* Unsent (queued) segments. */
|
||||
struct tcp_seg *unacked; /* Sent but unacknowledged segments. */
|
||||
@@ -366,49 +248,16 @@ struct tcp_pcb {
|
||||
struct pbuf *refused_data; /* Data previously received but not yet taken by upper layer */
|
||||
|
||||
#if LWIP_CALLBACK_API
|
||||
/* Function to be called when more send buffer space is available.
|
||||
* @param arg user-supplied argument (tcp_pcb.callback_arg)
|
||||
* @param pcb the tcp_pcb which has send buffer space available
|
||||
* @param space the amount of bytes available
|
||||
* @return ERR_OK: try to send some data by calling tcp_output
|
||||
*/
|
||||
err_t (* sent)(void *arg, struct tcp_pcb *pcb, u16_t space);
|
||||
|
||||
/* Function to be called when (in-sequence) data has arrived.
|
||||
* @param arg user-supplied argument (tcp_pcb.callback_arg)
|
||||
* @param pcb the tcp_pcb for which data has arrived
|
||||
* @param p the packet buffer which arrived
|
||||
* @param err an error argument (TODO: that is current always ERR_OK?)
|
||||
* @return ERR_OK: try to send some data by calling tcp_output
|
||||
*/
|
||||
err_t (* recv)(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
|
||||
|
||||
/* Function to be called when a connection has been set up.
|
||||
* @param arg user-supplied argument (tcp_pcb.callback_arg)
|
||||
* @param pcb the tcp_pcb that now is connected
|
||||
* @param err an error argument (TODO: that is current always ERR_OK?)
|
||||
* @return value is currently ignored
|
||||
*/
|
||||
err_t (* connected)(void *arg, struct tcp_pcb *pcb, err_t err);
|
||||
|
||||
/* Function which is called periodically.
|
||||
* The period can be adjusted in multiples of the TCP slow timer interval
|
||||
* by changing tcp_pcb.polltmr.
|
||||
* @param arg user-supplied argument (tcp_pcb.callback_arg)
|
||||
* @param pcb the tcp_pcb to poll for
|
||||
* @return ERR_OK: try to send some data by calling tcp_output
|
||||
*/
|
||||
err_t (* poll)(void *arg, struct tcp_pcb *pcb);
|
||||
|
||||
/* Function to be called whenever a fatal error occurs.
|
||||
* There is no pcb parameter since most of the times, the pcb is
|
||||
* already deallocated (or there is no pcb) when this function is called.
|
||||
* @param arg user-supplied argument (tcp_pcb.callback_arg)
|
||||
* @param err an indication why the error callback is called:
|
||||
* ERR_ABRT: aborted through tcp_abort or by a TCP timer
|
||||
* ERR_RST: the connection was reset by the remote host
|
||||
*/
|
||||
void (* errf)(void *arg, err_t err);
|
||||
/* Function to be called when more send buffer space is available. */
|
||||
tcp_sent_fn sent;
|
||||
/* Function to be called when (in-sequence) data has arrived. */
|
||||
tcp_recv_fn recv;
|
||||
/* Function to be called when a connection has been set up. */
|
||||
tcp_connected_fn connected;
|
||||
/* Function which is called periodically. */
|
||||
tcp_poll_fn poll;
|
||||
/* Function to be called whenever a fatal error occurs. */
|
||||
tcp_err_fn errf;
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
|
||||
#if LWIP_TCP_TIMESTAMPS
|
||||
@@ -424,7 +273,7 @@ struct tcp_pcb {
|
||||
#endif /* LWIP_TCP_KEEPALIVE */
|
||||
|
||||
/* Persist timer counter */
|
||||
u32_t persist_cnt;
|
||||
u8_t persist_cnt;
|
||||
/* Persist timer back-off */
|
||||
u8_t persist_backoff;
|
||||
|
||||
@@ -461,242 +310,65 @@ err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
|
||||
u16_t size,
|
||||
err_t err);
|
||||
|
||||
#define TCP_EVENT_ACCEPT(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
||||
LWIP_EVENT_ACCEPT, NULL, 0, err)
|
||||
#define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
||||
LWIP_EVENT_SENT, NULL, space, ERR_OK)
|
||||
#define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
||||
LWIP_EVENT_RECV, (p), 0, (err))
|
||||
#define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
||||
LWIP_EVENT_CONNECTED, NULL, 0, (err))
|
||||
#define TCP_EVENT_POLL(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
||||
LWIP_EVENT_POLL, NULL, 0, ERR_OK)
|
||||
#define TCP_EVENT_ERR(errf,arg,err) lwip_tcp_event((arg), NULL, \
|
||||
LWIP_EVENT_ERR, NULL, 0, (err))
|
||||
#else /* LWIP_EVENT_API */
|
||||
|
||||
#define TCP_EVENT_ACCEPT(pcb,err,ret) \
|
||||
do { \
|
||||
if((pcb)->accept != NULL) \
|
||||
(ret) = (pcb)->accept((pcb)->callback_arg,(pcb),(err)); \
|
||||
else (ret) = ERR_OK; \
|
||||
} while (0)
|
||||
|
||||
#define TCP_EVENT_SENT(pcb,space,ret) \
|
||||
do { \
|
||||
if((pcb)->sent != NULL) \
|
||||
(ret) = (pcb)->sent((pcb)->callback_arg,(pcb),(space)); \
|
||||
else (ret) = ERR_OK; \
|
||||
} while (0)
|
||||
|
||||
#define TCP_EVENT_RECV(pcb,p,err,ret) \
|
||||
do { \
|
||||
if((pcb)->recv != NULL) { \
|
||||
(ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); \
|
||||
} else { \
|
||||
(ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define TCP_EVENT_CONNECTED(pcb,err,ret) \
|
||||
do { \
|
||||
if((pcb)->connected != NULL) \
|
||||
(ret) = (pcb)->connected((pcb)->callback_arg,(pcb),(err)); \
|
||||
else (ret) = ERR_OK; \
|
||||
} while (0)
|
||||
|
||||
#define TCP_EVENT_POLL(pcb,ret) \
|
||||
do { \
|
||||
if((pcb)->poll != NULL) \
|
||||
(ret) = (pcb)->poll((pcb)->callback_arg,(pcb)); \
|
||||
else (ret) = ERR_OK; \
|
||||
} while (0)
|
||||
|
||||
#define TCP_EVENT_ERR(errf,arg,err) \
|
||||
do { \
|
||||
if((errf) != NULL) \
|
||||
(errf)((arg),(err)); \
|
||||
} while (0)
|
||||
|
||||
#endif /* LWIP_EVENT_API */
|
||||
|
||||
/* This structure represents a TCP segment on the unsent and unacked queues */
|
||||
struct tcp_seg {
|
||||
struct tcp_seg *next; /* used when putting segements on a queue */
|
||||
struct pbuf *p; /* buffer containing data + TCP header */
|
||||
void *dataptr; /* pointer to the TCP data in the pbuf */
|
||||
u16_t len; /* the TCP length of this segment */
|
||||
u8_t flags;
|
||||
#define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */
|
||||
#define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */
|
||||
struct tcp_hdr *tcphdr; /* the TCP header */
|
||||
};
|
||||
/* Application program's interface: */
|
||||
struct tcp_pcb * tcp_new (void);
|
||||
|
||||
#define LWIP_TCP_OPT_LENGTH(flags) \
|
||||
(flags & TF_SEG_OPTS_MSS ? 4 : 0) + \
|
||||
(flags & TF_SEG_OPTS_TS ? 12 : 0)
|
||||
void tcp_arg (struct tcp_pcb *pcb, void *arg);
|
||||
void tcp_accept (struct tcp_pcb *pcb, tcp_accept_fn accept);
|
||||
void tcp_recv (struct tcp_pcb *pcb, tcp_recv_fn recv);
|
||||
void tcp_sent (struct tcp_pcb *pcb, tcp_sent_fn sent);
|
||||
void tcp_poll (struct tcp_pcb *pcb, tcp_poll_fn poll, u8_t interval);
|
||||
void tcp_err (struct tcp_pcb *pcb, tcp_err_fn err);
|
||||
|
||||
/** This returns a TCP header option for MSS in an u32_t */
|
||||
#define TCP_BUILD_MSS_OPTION(x) (x) = htonl(((u32_t)2 << 24) | \
|
||||
((u32_t)4 << 16) | \
|
||||
(((u32_t)TCP_MSS / 256) << 8) | \
|
||||
(TCP_MSS & 255))
|
||||
#define tcp_mss(pcb) (((pcb)->flags & TF_TIMESTAMP) ? ((pcb)->mss - 12) : (pcb)->mss)
|
||||
#define tcp_sndbuf(pcb) ((pcb)->snd_buf)
|
||||
#define tcp_sndqueuelen(pcb) ((pcb)->snd_queuelen)
|
||||
#define tcp_nagle_disable(pcb) ((pcb)->flags |= TF_NODELAY)
|
||||
#define tcp_nagle_enable(pcb) ((pcb)->flags &= ~TF_NODELAY)
|
||||
#define tcp_nagle_disabled(pcb) (((pcb)->flags & TF_NODELAY) != 0)
|
||||
|
||||
/* Internal functions and global variables: */
|
||||
struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb);
|
||||
void tcp_pcb_purge(struct tcp_pcb *pcb);
|
||||
void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb);
|
||||
#if TCP_LISTEN_BACKLOG
|
||||
#define tcp_accepted(pcb) do { \
|
||||
LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", pcb->state == LISTEN); \
|
||||
(((struct tcp_pcb_listen *)(pcb))->accepts_pending--); } while(0)
|
||||
#else /* TCP_LISTEN_BACKLOG */
|
||||
#define tcp_accepted(pcb) LWIP_ASSERT("pcb->state == LISTEN (called for wrong pcb?)", \
|
||||
(pcb)->state == LISTEN)
|
||||
#endif /* TCP_LISTEN_BACKLOG */
|
||||
|
||||
u8_t tcp_segs_free(struct tcp_seg *seg);
|
||||
u8_t tcp_seg_free(struct tcp_seg *seg);
|
||||
struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg);
|
||||
void tcp_recved (struct tcp_pcb *pcb, u16_t len);
|
||||
err_t tcp_bind (struct tcp_pcb *pcb, ip_addr_t *ipaddr,
|
||||
u16_t port);
|
||||
err_t tcp_connect (struct tcp_pcb *pcb, ip_addr_t *ipaddr,
|
||||
u16_t port, tcp_connected_fn connected);
|
||||
|
||||
#define tcp_ack(pcb) \
|
||||
do { \
|
||||
if((pcb)->flags & TF_ACK_DELAY) { \
|
||||
(pcb)->flags &= ~TF_ACK_DELAY; \
|
||||
(pcb)->flags |= TF_ACK_NOW; \
|
||||
tcp_output(pcb); \
|
||||
} \
|
||||
else { \
|
||||
(pcb)->flags |= TF_ACK_DELAY; \
|
||||
} \
|
||||
} while (0)
|
||||
struct tcp_pcb * tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog);
|
||||
#define tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG)
|
||||
|
||||
#define tcp_ack_now(pcb) \
|
||||
do { \
|
||||
(pcb)->flags |= TF_ACK_NOW; \
|
||||
tcp_output(pcb); \
|
||||
} while (0)
|
||||
void tcp_abort (struct tcp_pcb *pcb);
|
||||
err_t tcp_close (struct tcp_pcb *pcb);
|
||||
err_t tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx);
|
||||
|
||||
err_t tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags);
|
||||
err_t tcp_enqueue(struct tcp_pcb *pcb, void *dataptr, u16_t len,
|
||||
u8_t flags, u8_t apiflags, u8_t optflags);
|
||||
/* Flags for "apiflags" parameter in tcp_write */
|
||||
#define TCP_WRITE_FLAG_COPY 0x01
|
||||
#define TCP_WRITE_FLAG_MORE 0x02
|
||||
|
||||
void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg);
|
||||
err_t tcp_write (struct tcp_pcb *pcb, const void *dataptr, u16_t len,
|
||||
u8_t apiflags);
|
||||
|
||||
void tcp_rst(u32_t seqno, u32_t ackno,
|
||||
struct ip_addr *local_ip, struct ip_addr *remote_ip,
|
||||
u16_t local_port, u16_t remote_port);
|
||||
void tcp_setprio (struct tcp_pcb *pcb, u8_t prio);
|
||||
|
||||
u32_t tcp_next_iss(void);
|
||||
#define TCP_PRIO_MIN 1
|
||||
#define TCP_PRIO_NORMAL 64
|
||||
#define TCP_PRIO_MAX 127
|
||||
|
||||
void tcp_keepalive(struct tcp_pcb *pcb);
|
||||
void tcp_zero_window_probe(struct tcp_pcb *pcb);
|
||||
err_t tcp_output (struct tcp_pcb *pcb);
|
||||
|
||||
#if TCP_CALCULATE_EFF_SEND_MSS
|
||||
u16_t tcp_eff_send_mss(u16_t sendmss, struct ip_addr *addr);
|
||||
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
||||
|
||||
#if LWIP_CALLBACK_API
|
||||
err_t tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
|
||||
extern struct tcp_pcb *tcp_input_pcb;
|
||||
extern u32_t tcp_ticks;
|
||||
|
||||
const char* tcp_debug_state_str(enum tcp_state s);
|
||||
#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
|
||||
void tcp_debug_print(struct tcp_hdr *tcphdr);
|
||||
void tcp_debug_print_flags(u8_t flags);
|
||||
void tcp_debug_print_state(enum tcp_state s);
|
||||
void tcp_debug_print_pcbs(void);
|
||||
s16_t tcp_pcbs_sane(void);
|
||||
#else
|
||||
# define tcp_debug_print(tcphdr)
|
||||
# define tcp_debug_print_flags(flags)
|
||||
# define tcp_debug_print_state(s)
|
||||
# define tcp_debug_print_pcbs()
|
||||
# define tcp_pcbs_sane() 1
|
||||
#endif /* TCP_DEBUG */
|
||||
|
||||
#if NO_SYS
|
||||
#define tcp_timer_needed()
|
||||
#else
|
||||
void tcp_timer_needed(void);
|
||||
#endif
|
||||
|
||||
/* The TCP PCB lists. */
|
||||
union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */
|
||||
struct tcp_pcb_listen *listen_pcbs;
|
||||
struct tcp_pcb *pcbs;
|
||||
};
|
||||
extern union tcp_listen_pcbs_t tcp_listen_pcbs;
|
||||
extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a
|
||||
state in which they accept or send
|
||||
data. */
|
||||
extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */
|
||||
|
||||
extern struct tcp_pcb *tcp_tmp_pcb; /* Only used for temporary storage. */
|
||||
|
||||
/* Axioms about the above lists:
|
||||
1) Every TCP PCB that is not CLOSED is in one of the lists.
|
||||
2) A PCB is only in one of the lists.
|
||||
3) All PCBs in the tcp_listen_pcbs list is in LISTEN state.
|
||||
4) All PCBs in the tcp_tw_pcbs list is in TIME-WAIT state.
|
||||
*/
|
||||
|
||||
/* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB
|
||||
with a PCB list or removes a PCB from a list, respectively. */
|
||||
#if 0
|
||||
#define TCP_REG(pcbs, npcb) do {\
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", npcb, npcb->local_port)); \
|
||||
for(tcp_tmp_pcb = *pcbs; \
|
||||
tcp_tmp_pcb != NULL; \
|
||||
tcp_tmp_pcb = tcp_tmp_pcb->next) { \
|
||||
LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != npcb); \
|
||||
} \
|
||||
LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", npcb->state != CLOSED); \
|
||||
npcb->next = *pcbs; \
|
||||
LWIP_ASSERT("TCP_REG: npcb->next != npcb", npcb->next != npcb); \
|
||||
*(pcbs) = npcb; \
|
||||
LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
|
||||
tcp_timer_needed(); \
|
||||
} while(0)
|
||||
#define TCP_RMV(pcbs, npcb) do { \
|
||||
LWIP_ASSERT("TCP_RMV: pcbs != NULL", *pcbs != NULL); \
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", npcb, *pcbs)); \
|
||||
if(*pcbs == npcb) { \
|
||||
*pcbs = (*pcbs)->next; \
|
||||
} else for(tcp_tmp_pcb = *pcbs; tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \
|
||||
if(tcp_tmp_pcb->next == npcb) { \
|
||||
tcp_tmp_pcb->next = npcb->next; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
npcb->next = NULL; \
|
||||
LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", npcb, *pcbs)); \
|
||||
} while(0)
|
||||
|
||||
#else /* LWIP_DEBUG */
|
||||
|
||||
#define TCP_REG(pcbs, npcb) \
|
||||
do { \
|
||||
npcb->next = *pcbs; \
|
||||
*(pcbs) = npcb; \
|
||||
tcp_timer_needed(); \
|
||||
} while (0)
|
||||
|
||||
#define TCP_RMV(pcbs, npcb) \
|
||||
do { \
|
||||
if(*(pcbs) == npcb) { \
|
||||
(*(pcbs)) = (*pcbs)->next; \
|
||||
} \
|
||||
else { \
|
||||
for(tcp_tmp_pcb = *pcbs; \
|
||||
tcp_tmp_pcb != NULL; \
|
||||
tcp_tmp_pcb = tcp_tmp_pcb->next) { \
|
||||
if(tcp_tmp_pcb->next == npcb) { \
|
||||
tcp_tmp_pcb->next = npcb->next; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
npcb->next = NULL; \
|
||||
} while(0)
|
||||
|
||||
#endif /* LWIP_DEBUG */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
486
src/include/lwip/tcp_impl.h
Normal file
486
src/include/lwip/tcp_impl.h
Normal file
@@ -0,0 +1,486 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_TCP_IMPL_H__
|
||||
#define __LWIP_TCP_IMPL_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_TCP /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/icmp.h"
|
||||
#include "lwip/err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Functions for interfacing with TCP: */
|
||||
|
||||
/* Lower layer interface to TCP: */
|
||||
void tcp_init (void); /* Initialize this module. */
|
||||
void tcp_tmr (void); /* Must be called every
|
||||
TCP_TMR_INTERVAL
|
||||
ms. (Typically 250 ms). */
|
||||
/* It is also possible to call these two functions at the right
|
||||
intervals (instead of calling tcp_tmr()). */
|
||||
void tcp_slowtmr (void);
|
||||
void tcp_fasttmr (void);
|
||||
|
||||
|
||||
/* Only used by IP to pass a TCP segment to TCP: */
|
||||
void tcp_input (struct pbuf *p, struct netif *inp);
|
||||
/* Used within the TCP code only: */
|
||||
struct tcp_pcb * tcp_alloc (u8_t prio);
|
||||
void tcp_abandon (struct tcp_pcb *pcb, int reset);
|
||||
err_t tcp_send_empty_ack(struct tcp_pcb *pcb);
|
||||
void tcp_rexmit (struct tcp_pcb *pcb);
|
||||
void tcp_rexmit_rto (struct tcp_pcb *pcb);
|
||||
void tcp_rexmit_fast (struct tcp_pcb *pcb);
|
||||
u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb);
|
||||
err_t tcp_process_refused_data(struct tcp_pcb *pcb);
|
||||
|
||||
/**
|
||||
* This is the Nagle algorithm: try to combine user data to send as few TCP
|
||||
* segments as possible. Only send if
|
||||
* - no previously transmitted data on the connection remains unacknowledged or
|
||||
* - the TF_NODELAY flag is set (nagle algorithm turned off for this pcb) or
|
||||
* - the only unsent segment is at least pcb->mss bytes long (or there is more
|
||||
* than one unsent segment - with lwIP, this can happen although unsent->len < mss)
|
||||
* - or if we are in fast-retransmit (TF_INFR)
|
||||
*/
|
||||
#define tcp_do_output_nagle(tpcb) ((((tpcb)->unacked == NULL) || \
|
||||
((tpcb)->flags & (TF_NODELAY | TF_INFR)) || \
|
||||
(((tpcb)->unsent != NULL) && (((tpcb)->unsent->next != NULL) || \
|
||||
((tpcb)->unsent->len >= (tpcb)->mss))) || \
|
||||
((tcp_sndbuf(tpcb) == 0) || (tcp_sndqueuelen(tpcb) >= TCP_SND_QUEUELEN)) \
|
||||
) ? 1 : 0)
|
||||
#define tcp_output_nagle(tpcb) (tcp_do_output_nagle(tpcb) ? tcp_output(tpcb) : ERR_OK)
|
||||
|
||||
|
||||
#define TCP_SEQ_LT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) < 0)
|
||||
#define TCP_SEQ_LEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) <= 0)
|
||||
#define TCP_SEQ_GT(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) > 0)
|
||||
#define TCP_SEQ_GEQ(a,b) ((s32_t)((u32_t)(a) - (u32_t)(b)) >= 0)
|
||||
/* is b<=a<=c? */
|
||||
#if 0 /* see bug #10548 */
|
||||
#define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b))
|
||||
#endif
|
||||
#define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c))
|
||||
#define TCP_FIN 0x01U
|
||||
#define TCP_SYN 0x02U
|
||||
#define TCP_RST 0x04U
|
||||
#define TCP_PSH 0x08U
|
||||
#define TCP_ACK 0x10U
|
||||
#define TCP_URG 0x20U
|
||||
#define TCP_ECE 0x40U
|
||||
#define TCP_CWR 0x80U
|
||||
|
||||
#define TCP_FLAGS 0x3fU
|
||||
|
||||
/* Length of the TCP header, excluding options. */
|
||||
#define TCP_HLEN 20
|
||||
|
||||
#ifndef TCP_TMR_INTERVAL
|
||||
#define TCP_TMR_INTERVAL 250 /* The TCP timer interval in milliseconds. */
|
||||
#endif /* TCP_TMR_INTERVAL */
|
||||
|
||||
#ifndef TCP_FAST_INTERVAL
|
||||
#define TCP_FAST_INTERVAL TCP_TMR_INTERVAL /* the fine grained timeout in milliseconds */
|
||||
#endif /* TCP_FAST_INTERVAL */
|
||||
|
||||
#ifndef TCP_SLOW_INTERVAL
|
||||
#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) /* the coarse grained timeout in milliseconds */
|
||||
#endif /* TCP_SLOW_INTERVAL */
|
||||
|
||||
#define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */
|
||||
#define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */
|
||||
|
||||
#define TCP_OOSEQ_TIMEOUT 6U /* x RTO */
|
||||
|
||||
#ifndef TCP_MSL
|
||||
#define TCP_MSL 60000UL /* The maximum segment lifetime in milliseconds */
|
||||
#endif
|
||||
|
||||
/* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */
|
||||
#ifndef TCP_KEEPIDLE_DEFAULT
|
||||
#define TCP_KEEPIDLE_DEFAULT 7200000UL /* Default KEEPALIVE timer in milliseconds */
|
||||
#endif
|
||||
|
||||
#ifndef TCP_KEEPINTVL_DEFAULT
|
||||
#define TCP_KEEPINTVL_DEFAULT 75000UL /* Default Time between KEEPALIVE probes in milliseconds */
|
||||
#endif
|
||||
|
||||
#ifndef TCP_KEEPCNT_DEFAULT
|
||||
#define TCP_KEEPCNT_DEFAULT 9U /* Default Counter for KEEPALIVE probes */
|
||||
#endif
|
||||
|
||||
#define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT /* Maximum KEEPALIVE probe time */
|
||||
|
||||
/* Fields are (of course) in network byte order.
|
||||
* Some fields are converted to host byte order in tcp_input().
|
||||
*/
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct tcp_hdr {
|
||||
PACK_STRUCT_FIELD(u16_t src);
|
||||
PACK_STRUCT_FIELD(u16_t dest);
|
||||
PACK_STRUCT_FIELD(u32_t seqno);
|
||||
PACK_STRUCT_FIELD(u32_t ackno);
|
||||
PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags);
|
||||
PACK_STRUCT_FIELD(u16_t wnd);
|
||||
PACK_STRUCT_FIELD(u16_t chksum);
|
||||
PACK_STRUCT_FIELD(u16_t urgp);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12)
|
||||
#define TCPH_FLAGS(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)
|
||||
|
||||
#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr))
|
||||
#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS((u16_t)(~(u16_t)(TCP_FLAGS)))) | htons(flags))
|
||||
#define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | (flags))
|
||||
|
||||
#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | htons(flags))
|
||||
#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) )
|
||||
|
||||
#define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0))
|
||||
|
||||
/** Flags used on input processing, not on pcb->flags
|
||||
*/
|
||||
#define TF_RESET (u8_t)0x08U /* Connection was reset. */
|
||||
#define TF_CLOSED (u8_t)0x10U /* Connection was sucessfully closed. */
|
||||
#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */
|
||||
|
||||
|
||||
#if LWIP_EVENT_API
|
||||
|
||||
#define TCP_EVENT_ACCEPT(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
||||
LWIP_EVENT_ACCEPT, NULL, 0, err)
|
||||
#define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
||||
LWIP_EVENT_SENT, NULL, space, ERR_OK)
|
||||
#define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
||||
LWIP_EVENT_RECV, (p), 0, (err))
|
||||
#define TCP_EVENT_CLOSED(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
||||
LWIP_EVENT_RECV, NULL, 0, ERR_OK)
|
||||
#define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
||||
LWIP_EVENT_CONNECTED, NULL, 0, (err))
|
||||
#define TCP_EVENT_POLL(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
||||
LWIP_EVENT_POLL, NULL, 0, ERR_OK)
|
||||
#define TCP_EVENT_ERR(errf,arg,err) lwip_tcp_event((arg), NULL, \
|
||||
LWIP_EVENT_ERR, NULL, 0, (err))
|
||||
|
||||
#else /* LWIP_EVENT_API */
|
||||
|
||||
#define TCP_EVENT_ACCEPT(pcb,err,ret) \
|
||||
do { \
|
||||
if((pcb)->accept != NULL) \
|
||||
(ret) = (pcb)->accept((pcb)->callback_arg,(pcb),(err)); \
|
||||
else (ret) = ERR_ARG; \
|
||||
} while (0)
|
||||
|
||||
#define TCP_EVENT_SENT(pcb,space,ret) \
|
||||
do { \
|
||||
if((pcb)->sent != NULL) \
|
||||
(ret) = (pcb)->sent((pcb)->callback_arg,(pcb),(space)); \
|
||||
else (ret) = ERR_OK; \
|
||||
} while (0)
|
||||
|
||||
#define TCP_EVENT_RECV(pcb,p,err,ret) \
|
||||
do { \
|
||||
if((pcb)->recv != NULL) { \
|
||||
(ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err));\
|
||||
} else { \
|
||||
(ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define TCP_EVENT_CLOSED(pcb,ret) \
|
||||
do { \
|
||||
if(((pcb)->recv != NULL)) { \
|
||||
(ret) = (pcb)->recv((pcb)->callback_arg,(pcb),NULL,ERR_OK);\
|
||||
} else { \
|
||||
(ret) = ERR_OK; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define TCP_EVENT_CONNECTED(pcb,err,ret) \
|
||||
do { \
|
||||
if((pcb)->connected != NULL) \
|
||||
(ret) = (pcb)->connected((pcb)->callback_arg,(pcb),(err)); \
|
||||
else (ret) = ERR_OK; \
|
||||
} while (0)
|
||||
|
||||
#define TCP_EVENT_POLL(pcb,ret) \
|
||||
do { \
|
||||
if((pcb)->poll != NULL) \
|
||||
(ret) = (pcb)->poll((pcb)->callback_arg,(pcb)); \
|
||||
else (ret) = ERR_OK; \
|
||||
} while (0)
|
||||
|
||||
#define TCP_EVENT_ERR(errf,arg,err) \
|
||||
do { \
|
||||
if((errf) != NULL) \
|
||||
(errf)((arg),(err)); \
|
||||
} while (0)
|
||||
|
||||
#endif /* LWIP_EVENT_API */
|
||||
|
||||
/** Enabled extra-check for TCP_OVERSIZE if LWIP_DEBUG is enabled */
|
||||
#if TCP_OVERSIZE && defined(LWIP_DEBUG)
|
||||
#define TCP_OVERSIZE_DBGCHECK 1
|
||||
#else
|
||||
#define TCP_OVERSIZE_DBGCHECK 0
|
||||
#endif
|
||||
|
||||
/** Don't generate checksum on copy if CHECKSUM_GEN_TCP is disabled */
|
||||
#define TCP_CHECKSUM_ON_COPY (LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_TCP)
|
||||
|
||||
/* This structure represents a TCP segment on the unsent, unacked and ooseq queues */
|
||||
struct tcp_seg {
|
||||
struct tcp_seg *next; /* used when putting segements on a queue */
|
||||
struct pbuf *p; /* buffer containing data + TCP header */
|
||||
u16_t len; /* the TCP length of this segment */
|
||||
#if TCP_OVERSIZE_DBGCHECK
|
||||
u16_t oversize_left; /* Extra bytes available at the end of the last
|
||||
pbuf in unsent (used for asserting vs.
|
||||
tcp_pcb.unsent_oversized only) */
|
||||
#endif /* TCP_OVERSIZE_DBGCHECK */
|
||||
#if TCP_CHECKSUM_ON_COPY
|
||||
u16_t chksum;
|
||||
u8_t chksum_swapped;
|
||||
#endif /* TCP_CHECKSUM_ON_COPY */
|
||||
u8_t flags;
|
||||
#define TF_SEG_OPTS_MSS (u8_t)0x01U /* Include MSS option. */
|
||||
#define TF_SEG_OPTS_TS (u8_t)0x02U /* Include timestamp option. */
|
||||
#define TF_SEG_DATA_CHECKSUMMED (u8_t)0x04U /* ALL data (not the header) is
|
||||
checksummed into 'chksum' */
|
||||
struct tcp_hdr *tcphdr; /* the TCP header */
|
||||
};
|
||||
|
||||
#define LWIP_TCP_OPT_LENGTH(flags) \
|
||||
(flags & TF_SEG_OPTS_MSS ? 4 : 0) + \
|
||||
(flags & TF_SEG_OPTS_TS ? 12 : 0)
|
||||
|
||||
/** This returns a TCP header option for MSS in an u32_t */
|
||||
#define TCP_BUILD_MSS_OPTION(mss) htonl(0x02040000 | ((mss) & 0xFFFF))
|
||||
|
||||
/* Global variables: */
|
||||
extern struct tcp_pcb *tcp_input_pcb;
|
||||
extern u32_t tcp_ticks;
|
||||
extern u8_t tcp_active_pcbs_changed;
|
||||
|
||||
/* The TCP PCB lists. */
|
||||
union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */
|
||||
struct tcp_pcb_listen *listen_pcbs;
|
||||
struct tcp_pcb *pcbs;
|
||||
};
|
||||
extern struct tcp_pcb *tcp_bound_pcbs;
|
||||
extern union tcp_listen_pcbs_t tcp_listen_pcbs;
|
||||
extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a
|
||||
state in which they accept or send
|
||||
data. */
|
||||
extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */
|
||||
|
||||
extern struct tcp_pcb *tcp_tmp_pcb; /* Only used for temporary storage. */
|
||||
|
||||
/* Axioms about the above lists:
|
||||
1) Every TCP PCB that is not CLOSED is in one of the lists.
|
||||
2) A PCB is only in one of the lists.
|
||||
3) All PCBs in the tcp_listen_pcbs list is in LISTEN state.
|
||||
4) All PCBs in the tcp_tw_pcbs list is in TIME-WAIT state.
|
||||
*/
|
||||
/* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB
|
||||
with a PCB list or removes a PCB from a list, respectively. */
|
||||
#ifndef TCP_DEBUG_PCB_LISTS
|
||||
#define TCP_DEBUG_PCB_LISTS 0
|
||||
#endif
|
||||
#if TCP_DEBUG_PCB_LISTS
|
||||
#define TCP_REG(pcbs, npcb) do {\
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", (npcb), (npcb)->local_port)); \
|
||||
for(tcp_tmp_pcb = *(pcbs); \
|
||||
tcp_tmp_pcb != NULL; \
|
||||
tcp_tmp_pcb = tcp_tmp_pcb->next) { \
|
||||
LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != (npcb)); \
|
||||
} \
|
||||
LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", ((pcbs) == &tcp_bound_pcbs) || ((npcb)->state != CLOSED)); \
|
||||
(npcb)->next = *(pcbs); \
|
||||
LWIP_ASSERT("TCP_REG: npcb->next != npcb", (npcb)->next != (npcb)); \
|
||||
*(pcbs) = (npcb); \
|
||||
LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
|
||||
tcp_timer_needed(); \
|
||||
} while(0)
|
||||
#define TCP_RMV(pcbs, npcb) do { \
|
||||
LWIP_ASSERT("TCP_RMV: pcbs != NULL", *(pcbs) != NULL); \
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", (npcb), *(pcbs))); \
|
||||
if(*(pcbs) == (npcb)) { \
|
||||
*(pcbs) = (*pcbs)->next; \
|
||||
} else for(tcp_tmp_pcb = *(pcbs); tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \
|
||||
if(tcp_tmp_pcb->next == (npcb)) { \
|
||||
tcp_tmp_pcb->next = (npcb)->next; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
(npcb)->next = NULL; \
|
||||
LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", (npcb), *(pcbs))); \
|
||||
} while(0)
|
||||
|
||||
#else /* LWIP_DEBUG */
|
||||
|
||||
#define TCP_REG(pcbs, npcb) \
|
||||
do { \
|
||||
(npcb)->next = *pcbs; \
|
||||
*(pcbs) = (npcb); \
|
||||
tcp_timer_needed(); \
|
||||
} while (0)
|
||||
|
||||
#define TCP_RMV(pcbs, npcb) \
|
||||
do { \
|
||||
if(*(pcbs) == (npcb)) { \
|
||||
(*(pcbs)) = (*pcbs)->next; \
|
||||
} \
|
||||
else { \
|
||||
for(tcp_tmp_pcb = *pcbs; \
|
||||
tcp_tmp_pcb != NULL; \
|
||||
tcp_tmp_pcb = tcp_tmp_pcb->next) { \
|
||||
if(tcp_tmp_pcb->next == (npcb)) { \
|
||||
tcp_tmp_pcb->next = (npcb)->next; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
(npcb)->next = NULL; \
|
||||
} while(0)
|
||||
|
||||
#endif /* LWIP_DEBUG */
|
||||
|
||||
#define TCP_REG_ACTIVE(npcb) \
|
||||
do { \
|
||||
TCP_REG(&tcp_active_pcbs, npcb); \
|
||||
tcp_active_pcbs_changed = 1; \
|
||||
} while (0)
|
||||
|
||||
#define TCP_RMV_ACTIVE(npcb) \
|
||||
do { \
|
||||
TCP_RMV(&tcp_active_pcbs, npcb); \
|
||||
tcp_active_pcbs_changed = 1; \
|
||||
} while (0)
|
||||
|
||||
#define TCP_PCB_REMOVE_ACTIVE(pcb) \
|
||||
do { \
|
||||
tcp_pcb_remove(&tcp_active_pcbs, pcb); \
|
||||
tcp_active_pcbs_changed = 1; \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* Internal functions: */
|
||||
struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb);
|
||||
void tcp_pcb_purge(struct tcp_pcb *pcb);
|
||||
void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb);
|
||||
|
||||
void tcp_segs_free(struct tcp_seg *seg);
|
||||
void tcp_seg_free(struct tcp_seg *seg);
|
||||
struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg);
|
||||
|
||||
#define tcp_ack(pcb) \
|
||||
do { \
|
||||
if((pcb)->flags & TF_ACK_DELAY) { \
|
||||
(pcb)->flags &= ~TF_ACK_DELAY; \
|
||||
(pcb)->flags |= TF_ACK_NOW; \
|
||||
} \
|
||||
else { \
|
||||
(pcb)->flags |= TF_ACK_DELAY; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define tcp_ack_now(pcb) \
|
||||
do { \
|
||||
(pcb)->flags |= TF_ACK_NOW; \
|
||||
} while (0)
|
||||
|
||||
err_t tcp_send_fin(struct tcp_pcb *pcb);
|
||||
err_t tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags);
|
||||
|
||||
void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg);
|
||||
|
||||
void tcp_rst(u32_t seqno, u32_t ackno,
|
||||
ip_addr_t *local_ip, ip_addr_t *remote_ip,
|
||||
u16_t local_port, u16_t remote_port);
|
||||
|
||||
u32_t tcp_next_iss(void);
|
||||
|
||||
void tcp_keepalive(struct tcp_pcb *pcb);
|
||||
void tcp_zero_window_probe(struct tcp_pcb *pcb);
|
||||
|
||||
#if TCP_CALCULATE_EFF_SEND_MSS
|
||||
u16_t tcp_eff_send_mss(u16_t sendmss, ip_addr_t *addr);
|
||||
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
|
||||
|
||||
#if LWIP_CALLBACK_API
|
||||
err_t tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
|
||||
#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
|
||||
void tcp_debug_print(struct tcp_hdr *tcphdr);
|
||||
void tcp_debug_print_flags(u8_t flags);
|
||||
void tcp_debug_print_state(enum tcp_state s);
|
||||
void tcp_debug_print_pcbs(void);
|
||||
s16_t tcp_pcbs_sane(void);
|
||||
#else
|
||||
# define tcp_debug_print(tcphdr)
|
||||
# define tcp_debug_print_flags(flags)
|
||||
# define tcp_debug_print_state(s)
|
||||
# define tcp_debug_print_pcbs()
|
||||
# define tcp_pcbs_sane() 1
|
||||
#endif /* TCP_DEBUG */
|
||||
|
||||
/** External function (implemented in timers.c), called when TCP detects
|
||||
* that a timer is needed (i.e. active- or time-wait-pcb found). */
|
||||
void tcp_timer_needed(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_TCP */
|
||||
|
||||
#endif /* __LWIP_TCP_H__ */
|
||||
@@ -41,31 +41,46 @@
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/api.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/timers.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Define this to something that triggers a watchdog. This is called from
|
||||
* tcpip_thread after processing a message. */
|
||||
#ifndef LWIP_TCPIP_THREAD_ALIVE
|
||||
#define LWIP_TCPIP_THREAD_ALIVE()
|
||||
#endif
|
||||
|
||||
#if LWIP_TCPIP_CORE_LOCKING
|
||||
/** The global semaphore to lock the stack. */
|
||||
extern sys_sem_t lock_tcpip_core;
|
||||
#define LOCK_TCPIP_CORE() sys_sem_wait(lock_tcpip_core)
|
||||
#define UNLOCK_TCPIP_CORE() sys_sem_signal(lock_tcpip_core)
|
||||
extern sys_mutex_t lock_tcpip_core;
|
||||
#define LOCK_TCPIP_CORE() sys_mutex_lock(&lock_tcpip_core)
|
||||
#define UNLOCK_TCPIP_CORE() sys_mutex_unlock(&lock_tcpip_core)
|
||||
#define TCPIP_APIMSG(m) tcpip_apimsg_lock(m)
|
||||
#define TCPIP_APIMSG_ACK(m)
|
||||
#define TCPIP_NETIFAPI(m) tcpip_netifapi_lock(m)
|
||||
#define TCPIP_NETIFAPI_ACK(m)
|
||||
#else
|
||||
#else /* LWIP_TCPIP_CORE_LOCKING */
|
||||
#define LOCK_TCPIP_CORE()
|
||||
#define UNLOCK_TCPIP_CORE()
|
||||
#define TCPIP_APIMSG(m) tcpip_apimsg(m)
|
||||
#define TCPIP_APIMSG_ACK(m) sys_sem_signal(m->conn->op_completed)
|
||||
#define TCPIP_APIMSG_ACK(m) sys_sem_signal(&m->conn->op_completed)
|
||||
#define TCPIP_NETIFAPI(m) tcpip_netifapi(m)
|
||||
#define TCPIP_NETIFAPI_ACK(m) sys_sem_signal(m->sem)
|
||||
#define TCPIP_NETIFAPI_ACK(m) sys_sem_signal(&m->sem)
|
||||
#endif /* LWIP_TCPIP_CORE_LOCKING */
|
||||
|
||||
void tcpip_init(void (* tcpip_init_done)(void *), void *arg);
|
||||
/** Function prototype for the init_done function passed to tcpip_init */
|
||||
typedef void (*tcpip_init_done_fn)(void *arg);
|
||||
/** Function prototype for functions passed to tcpip_callback() */
|
||||
typedef void (*tcpip_callback_fn)(void *ctx);
|
||||
|
||||
/* Forward declarations */
|
||||
struct tcpip_callback_msg;
|
||||
|
||||
void tcpip_init(tcpip_init_done_fn tcpip_init_done, void *arg);
|
||||
|
||||
#if LWIP_NETCONN
|
||||
err_t tcpip_apimsg(struct api_msg *apimsg);
|
||||
@@ -83,15 +98,21 @@ err_t tcpip_netifapi_lock(struct netifapi_msg *netifapimsg);
|
||||
#endif /* LWIP_TCPIP_CORE_LOCKING */
|
||||
#endif /* LWIP_NETIF_API */
|
||||
|
||||
err_t tcpip_callback_with_block(void (*f)(void *ctx), void *ctx, u8_t block);
|
||||
err_t tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block);
|
||||
#define tcpip_callback(f, ctx) tcpip_callback_with_block(f, ctx, 1)
|
||||
|
||||
struct tcpip_callback_msg* tcpip_callbackmsg_new(tcpip_callback_fn function, void *ctx);
|
||||
void tcpip_callbackmsg_delete(struct tcpip_callback_msg* msg);
|
||||
err_t tcpip_trycallback(struct tcpip_callback_msg* msg);
|
||||
|
||||
/* free pbufs or heap memory from another context without blocking */
|
||||
err_t pbuf_free_callback(struct pbuf *p);
|
||||
err_t mem_free_callback(void *m);
|
||||
|
||||
#if LWIP_TCPIP_TIMEOUT
|
||||
err_t tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg);
|
||||
err_t tcpip_untimeout(sys_timeout_handler h, void *arg);
|
||||
#endif /* LWIP_TCPIP_TIMEOUT */
|
||||
|
||||
enum tcpip_msg_type {
|
||||
#if LWIP_NETCONN
|
||||
@@ -101,9 +122,12 @@ enum tcpip_msg_type {
|
||||
#if LWIP_NETIF_API
|
||||
TCPIP_MSG_NETIFAPI,
|
||||
#endif /* LWIP_NETIF_API */
|
||||
TCPIP_MSG_CALLBACK,
|
||||
#if LWIP_TCPIP_TIMEOUT
|
||||
TCPIP_MSG_TIMEOUT,
|
||||
TCPIP_MSG_UNTIMEOUT
|
||||
TCPIP_MSG_UNTIMEOUT,
|
||||
#endif /* LWIP_TCPIP_TIMEOUT */
|
||||
TCPIP_MSG_CALLBACK,
|
||||
TCPIP_MSG_CALLBACK_STATIC
|
||||
};
|
||||
|
||||
struct tcpip_msg {
|
||||
@@ -121,14 +145,16 @@ struct tcpip_msg {
|
||||
struct netif *netif;
|
||||
} inp;
|
||||
struct {
|
||||
void (*f)(void *ctx);
|
||||
tcpip_callback_fn function;
|
||||
void *ctx;
|
||||
} cb;
|
||||
#if LWIP_TCPIP_TIMEOUT
|
||||
struct {
|
||||
u32_t msecs;
|
||||
sys_timeout_handler h;
|
||||
void *arg;
|
||||
} tmo;
|
||||
#endif /* LWIP_TCPIP_TIMEOUT */
|
||||
} msg;
|
||||
};
|
||||
|
||||
|
||||
100
src/include/lwip/timers.h
Normal file
100
src/include/lwip/timers.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
* Simon Goldschmidt
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_TIMERS_H__
|
||||
#define __LWIP_TIMERS_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
/* Timers are not supported when NO_SYS==1 and NO_SYS_NO_TIMERS==1 */
|
||||
#define LWIP_TIMERS (!NO_SYS || (NO_SYS && !NO_SYS_NO_TIMERS))
|
||||
|
||||
#if LWIP_TIMERS
|
||||
|
||||
#include "lwip/err.h"
|
||||
#if !NO_SYS
|
||||
#include "lwip/sys.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef LWIP_DEBUG_TIMERNAMES
|
||||
#ifdef LWIP_DEBUG
|
||||
#define LWIP_DEBUG_TIMERNAMES SYS_DEBUG
|
||||
#else /* LWIP_DEBUG */
|
||||
#define LWIP_DEBUG_TIMERNAMES 0
|
||||
#endif /* LWIP_DEBUG*/
|
||||
#endif
|
||||
|
||||
/** Function prototype for a timeout callback function. Register such a function
|
||||
* using sys_timeout().
|
||||
*
|
||||
* @param arg Additional argument to pass to the function - set up by sys_timeout()
|
||||
*/
|
||||
typedef void (* sys_timeout_handler)(void *arg);
|
||||
|
||||
struct sys_timeo {
|
||||
struct sys_timeo *next;
|
||||
u32_t time;
|
||||
sys_timeout_handler h;
|
||||
void *arg;
|
||||
#if LWIP_DEBUG_TIMERNAMES
|
||||
const char* handler_name;
|
||||
#endif /* LWIP_DEBUG_TIMERNAMES */
|
||||
};
|
||||
|
||||
void sys_timeouts_init(void);
|
||||
|
||||
#if LWIP_DEBUG_TIMERNAMES
|
||||
void sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name);
|
||||
#define sys_timeout(msecs, handler, arg) sys_timeout_debug(msecs, handler, arg, #handler)
|
||||
#else /* LWIP_DEBUG_TIMERNAMES */
|
||||
void sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg);
|
||||
#endif /* LWIP_DEBUG_TIMERNAMES */
|
||||
|
||||
void sys_untimeout(sys_timeout_handler handler, void *arg);
|
||||
#if NO_SYS
|
||||
void sys_check_timeouts(void);
|
||||
void sys_restart_timeouts(void);
|
||||
#else /* NO_SYS */
|
||||
void sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg);
|
||||
#endif /* NO_SYS */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_TIMERS */
|
||||
#endif /* __LWIP_TIMERS_H__ */
|
||||
@@ -63,9 +63,30 @@ PACK_STRUCT_END
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#define UDP_FLAGS_NOCHKSUM 0x01U
|
||||
#define UDP_FLAGS_UDPLITE 0x02U
|
||||
#define UDP_FLAGS_CONNECTED 0x04U
|
||||
#define UDP_FLAGS_NOCHKSUM 0x01U
|
||||
#define UDP_FLAGS_UDPLITE 0x02U
|
||||
#define UDP_FLAGS_CONNECTED 0x04U
|
||||
#define UDP_FLAGS_MULTICAST_LOOP 0x08U
|
||||
|
||||
struct udp_pcb;
|
||||
|
||||
/** Function prototype for udp pcb receive callback functions
|
||||
* addr and port are in same byte order as in the pcb
|
||||
* The callback is responsible for freeing the pbuf
|
||||
* if it's not used any more.
|
||||
*
|
||||
* ATTENTION: Be aware that 'addr' points into the pbuf 'p' so freeing this pbuf
|
||||
* makes 'addr' invalid, too.
|
||||
*
|
||||
* @param arg user supplied argument (udp_pcb.recv_arg)
|
||||
* @param pcb the udp_pcb which received data
|
||||
* @param p the packet buffer that was received
|
||||
* @param addr the remote IP address from which the packet was received
|
||||
* @param port the remote port from which the packet was received
|
||||
*/
|
||||
typedef void (*udp_recv_fn)(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
||||
ip_addr_t *addr, u16_t port);
|
||||
|
||||
|
||||
struct udp_pcb {
|
||||
/* Common members of all PCB types */
|
||||
@@ -76,36 +97,22 @@ struct udp_pcb {
|
||||
struct udp_pcb *next;
|
||||
|
||||
u8_t flags;
|
||||
/* ports are in host byte order */
|
||||
/** ports are in host byte order */
|
||||
u16_t local_port, remote_port;
|
||||
|
||||
#if LWIP_IGMP
|
||||
/* outgoing network interface for multicast packets */
|
||||
struct ip_addr multicast_ip;
|
||||
/** outgoing network interface for multicast packets */
|
||||
ip_addr_t multicast_ip;
|
||||
#endif /* LWIP_IGMP */
|
||||
|
||||
#if LWIP_UDPLITE
|
||||
/* used for UDP_LITE only */
|
||||
/** used for UDP_LITE only */
|
||||
u16_t chksum_len_rx, chksum_len_tx;
|
||||
#endif /* LWIP_UDPLITE */
|
||||
|
||||
/* receive callback function
|
||||
* addr and port are in same byte order as in the pcb
|
||||
* The callback is responsible for freeing the pbuf
|
||||
* if it's not used any more.
|
||||
*
|
||||
* ATTENTION: Be aware that 'addr' points into the pbuf 'p' so freeing this pbuf
|
||||
* makes 'addr' invalid, too.
|
||||
*
|
||||
* @param arg user supplied argument (udp_pcb.recv_arg)
|
||||
* @param pcb the udp_pcb which received data
|
||||
* @param p the packet buffer that was received
|
||||
* @param addr the remote IP address from which the packet was received
|
||||
* @param port the remote port from which the packet was received
|
||||
*/
|
||||
void (* recv)(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
||||
struct ip_addr *addr, u16_t port);
|
||||
/* user-supplied argument for the recv callback */
|
||||
/** receive callback function */
|
||||
udp_recv_fn recv;
|
||||
/** user-supplied argument for the recv callback */
|
||||
void *recv_arg;
|
||||
};
|
||||
/* udp_pcbs export for exernal reference (e.g. SNMP agent) */
|
||||
@@ -115,28 +122,39 @@ extern struct udp_pcb *udp_pcbs;
|
||||
UDP code. */
|
||||
struct udp_pcb * udp_new (void);
|
||||
void udp_remove (struct udp_pcb *pcb);
|
||||
err_t udp_bind (struct udp_pcb *pcb, struct ip_addr *ipaddr,
|
||||
u16_t port);
|
||||
err_t udp_connect (struct udp_pcb *pcb, struct ip_addr *ipaddr,
|
||||
u16_t port);
|
||||
void udp_disconnect (struct udp_pcb *pcb);
|
||||
void udp_recv (struct udp_pcb *pcb,
|
||||
void (* recv)(void *arg, struct udp_pcb *upcb,
|
||||
struct pbuf *p,
|
||||
struct ip_addr *addr,
|
||||
u16_t port),
|
||||
void *recv_arg);
|
||||
err_t udp_sendto_if (struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *dst_ip, u16_t dst_port, struct netif *netif);
|
||||
err_t udp_sendto (struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *dst_ip, u16_t dst_port);
|
||||
err_t udp_bind (struct udp_pcb *pcb, ip_addr_t *ipaddr,
|
||||
u16_t port);
|
||||
err_t udp_connect (struct udp_pcb *pcb, ip_addr_t *ipaddr,
|
||||
u16_t port);
|
||||
void udp_disconnect (struct udp_pcb *pcb);
|
||||
void udp_recv (struct udp_pcb *pcb, udp_recv_fn recv,
|
||||
void *recv_arg);
|
||||
err_t udp_sendto_if (struct udp_pcb *pcb, struct pbuf *p,
|
||||
ip_addr_t *dst_ip, u16_t dst_port,
|
||||
struct netif *netif);
|
||||
err_t udp_sendto (struct udp_pcb *pcb, struct pbuf *p,
|
||||
ip_addr_t *dst_ip, u16_t dst_port);
|
||||
err_t udp_send (struct udp_pcb *pcb, struct pbuf *p);
|
||||
|
||||
#define udp_flags(pcb) ((pcb)->flags)
|
||||
#if LWIP_CHECKSUM_ON_COPY
|
||||
err_t udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p,
|
||||
ip_addr_t *dst_ip, u16_t dst_port,
|
||||
struct netif *netif, u8_t have_chksum,
|
||||
u16_t chksum);
|
||||
err_t udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p,
|
||||
ip_addr_t *dst_ip, u16_t dst_port,
|
||||
u8_t have_chksum, u16_t chksum);
|
||||
err_t udp_send_chksum(struct udp_pcb *pcb, struct pbuf *p,
|
||||
u8_t have_chksum, u16_t chksum);
|
||||
#endif /* LWIP_CHECKSUM_ON_COPY */
|
||||
|
||||
#define udp_flags(pcb) ((pcb)->flags)
|
||||
#define udp_setflags(pcb, f) ((pcb)->flags = (f))
|
||||
|
||||
/* The following functions are the lower layer interface to UDP. */
|
||||
void udp_input (struct pbuf *p, struct netif *inp);
|
||||
|
||||
#define udp_init() /* Compatibility define, not init needed. */
|
||||
void udp_init (void);
|
||||
|
||||
#if UDP_DEBUG
|
||||
void udp_debug_print(struct udp_hdr *udphdr);
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_ARP /* don't build if not configured for use in lwipopts.h */
|
||||
#if LWIP_ARP || LWIP_ETHERNET /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
@@ -48,10 +48,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef ETH_PAD_SIZE
|
||||
#define ETH_PAD_SIZE 0
|
||||
#endif
|
||||
|
||||
#ifndef ETHARP_HWADDR_LEN
|
||||
#define ETHARP_HWADDR_LEN 6
|
||||
#endif
|
||||
@@ -72,6 +68,7 @@ PACK_STRUCT_END
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
/** Ethernet header */
|
||||
struct eth_hdr {
|
||||
#if ETH_PAD_SIZE
|
||||
PACK_STRUCT_FIELD(u8_t padding[ETH_PAD_SIZE]);
|
||||
@@ -93,9 +90,12 @@ PACK_STRUCT_END
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
/** VLAN header inserted between ethernet header and payload
|
||||
* if 'type' in ethernet header is ETHTYPE_VLAN.
|
||||
* See IEEE802.Q */
|
||||
struct eth_vlan_hdr {
|
||||
PACK_STRUCT_FIELD(u16_t tpid);
|
||||
PACK_STRUCT_FIELD(u16_t prio_vid);
|
||||
PACK_STRUCT_FIELD(u16_t tpid);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
@@ -111,11 +111,12 @@ PACK_STRUCT_END
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
/** the ARP message */
|
||||
/** the ARP message, see RFC 826 ("Packet format") */
|
||||
struct etharp_hdr {
|
||||
PACK_STRUCT_FIELD(u16_t hwtype);
|
||||
PACK_STRUCT_FIELD(u16_t proto);
|
||||
PACK_STRUCT_FIELD(u16_t _hwlen_protolen);
|
||||
PACK_STRUCT_FIELD(u8_t hwlen);
|
||||
PACK_STRUCT_FIELD(u8_t protolen);
|
||||
PACK_STRUCT_FIELD(u16_t opcode);
|
||||
PACK_STRUCT_FIELD(struct eth_addr shwaddr);
|
||||
PACK_STRUCT_FIELD(struct ip_addr2 sipaddr);
|
||||
@@ -133,16 +134,40 @@ PACK_STRUCT_END
|
||||
/** 5 seconds period */
|
||||
#define ARP_TMR_INTERVAL 5000
|
||||
|
||||
#define ETHTYPE_ARP 0x0806
|
||||
#define ETHTYPE_IP 0x0800
|
||||
#define ETHTYPE_VLAN 0x8100
|
||||
#define ETHTYPE_PPPOEDISC 0x8863 /* PPP Over Ethernet Discovery Stage */
|
||||
#define ETHTYPE_PPPOE 0x8864 /* PPP Over Ethernet Session Stage */
|
||||
#define ETHTYPE_ARP 0x0806U
|
||||
#define ETHTYPE_IP 0x0800U
|
||||
#define ETHTYPE_VLAN 0x8100U
|
||||
#define ETHTYPE_PPPOEDISC 0x8863U /* PPP Over Ethernet Discovery Stage */
|
||||
#define ETHTYPE_PPPOE 0x8864U /* PPP Over Ethernet Session Stage */
|
||||
|
||||
/** MEMCPY-like macro to copy to/from struct eth_addr's that are local variables
|
||||
* or known to be 32-bit aligned within the protocol header. */
|
||||
#ifndef ETHADDR32_COPY
|
||||
#define ETHADDR32_COPY(src, dst) SMEMCPY(src, dst, ETHARP_HWADDR_LEN)
|
||||
#endif
|
||||
|
||||
/** MEMCPY-like macro to copy to/from struct eth_addr's that are no local
|
||||
* variables and known to be 16-bit aligned within the protocol header. */
|
||||
#ifndef ETHADDR16_COPY
|
||||
#define ETHADDR16_COPY(src, dst) SMEMCPY(src, dst, ETHARP_HWADDR_LEN)
|
||||
#endif
|
||||
|
||||
#if LWIP_ARP /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
/** ARP message types (opcodes) */
|
||||
#define ARP_REQUEST 1
|
||||
#define ARP_REPLY 2
|
||||
|
||||
/** Define this to 1 and define LWIP_ARP_FILTER_NETIF_FN(pbuf, netif, type)
|
||||
* to a filter function that returns the correct netif when using multiple
|
||||
* netifs on one hardware interface where the netif's low-level receive
|
||||
* routine cannot decide for the correct netif (e.g. when mapping multiple
|
||||
* IP addresses to one hardware interface).
|
||||
*/
|
||||
#ifndef LWIP_ARP_FILTER_NETIF
|
||||
#define LWIP_ARP_FILTER_NETIF 0
|
||||
#endif
|
||||
|
||||
#if ARP_QUEUEING
|
||||
/** struct for queueing outgoing packets for unknown address
|
||||
* defined here to be accessed by memp.h
|
||||
@@ -155,38 +180,43 @@ struct etharp_q_entry {
|
||||
|
||||
#define etharp_init() /* Compatibility define, not init needed. */
|
||||
void etharp_tmr(void);
|
||||
s8_t etharp_find_addr(struct netif *netif, struct ip_addr *ipaddr,
|
||||
struct eth_addr **eth_ret, struct ip_addr **ip_ret);
|
||||
void etharp_ip_input(struct netif *netif, struct pbuf *p);
|
||||
void etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr,
|
||||
struct pbuf *p);
|
||||
err_t etharp_output(struct netif *netif, struct pbuf *q, struct ip_addr *ipaddr);
|
||||
err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q);
|
||||
err_t etharp_request(struct netif *netif, struct ip_addr *ipaddr);
|
||||
s8_t etharp_find_addr(struct netif *netif, ip_addr_t *ipaddr,
|
||||
struct eth_addr **eth_ret, ip_addr_t **ip_ret);
|
||||
err_t etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr);
|
||||
err_t etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q);
|
||||
err_t etharp_request(struct netif *netif, ip_addr_t *ipaddr);
|
||||
/** For Ethernet network interfaces, we might want to send "gratuitous ARP";
|
||||
* this is an ARP packet sent by a node in order to spontaneously cause other
|
||||
* nodes to update an entry in their ARP cache.
|
||||
* From RFC 3220 "IP Mobility Support for IPv4" section 4.6. */
|
||||
#define etharp_gratuitous(netif) etharp_request((netif), &(netif)->ip_addr)
|
||||
void etharp_cleanup_netif(struct netif *netif);
|
||||
|
||||
err_t ethernet_input(struct pbuf *p, struct netif *netif);
|
||||
#if ETHARP_SUPPORT_STATIC_ENTRIES
|
||||
err_t etharp_add_static_entry(ip_addr_t *ipaddr, struct eth_addr *ethaddr);
|
||||
err_t etharp_remove_static_entry(ip_addr_t *ipaddr);
|
||||
#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
|
||||
|
||||
#if LWIP_AUTOIP
|
||||
err_t etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr,
|
||||
const struct eth_addr *ethdst_addr,
|
||||
const struct eth_addr *hwsrc_addr, const struct ip_addr *ipsrc_addr,
|
||||
const struct eth_addr *hwdst_addr, const struct ip_addr *ipdst_addr,
|
||||
const struct eth_addr *hwsrc_addr, const ip_addr_t *ipsrc_addr,
|
||||
const struct eth_addr *hwdst_addr, const ip_addr_t *ipdst_addr,
|
||||
const u16_t opcode);
|
||||
#endif /* LWIP_AUTOIP */
|
||||
|
||||
#endif /* LWIP_ARP */
|
||||
|
||||
err_t ethernet_input(struct pbuf *p, struct netif *netif);
|
||||
|
||||
#define eth_addr_cmp(addr1, addr2) (memcmp((addr1)->addr, (addr2)->addr, ETHARP_HWADDR_LEN) == 0)
|
||||
|
||||
extern const struct eth_addr ethbroadcast, ethzero;
|
||||
|
||||
#endif /* LWIP_ARP || LWIP_ETHERNET */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_ARP */
|
||||
|
||||
#endif /* __NETIF_ARP_H__ */
|
||||
|
||||
@@ -74,15 +74,17 @@
|
||||
|
||||
#if PPPOE_SUPPORT > 0
|
||||
|
||||
#include "netif/etharp.h"
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct pppoehdr {
|
||||
PACK_STRUCT_FIELD(u8_t vertype);
|
||||
PACK_STRUCT_FIELD(u8_t code);
|
||||
PACK_STRUCT_FIELD(u16_t session);
|
||||
PACK_STRUCT_FIELD(u16_t plen);
|
||||
PACK_STRUCT_FIELD(u8_t vertype);
|
||||
PACK_STRUCT_FIELD(u8_t code);
|
||||
PACK_STRUCT_FIELD(u16_t session);
|
||||
PACK_STRUCT_FIELD(u16_t plen);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
@@ -94,8 +96,8 @@ PACK_STRUCT_END
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct pppoetag {
|
||||
PACK_STRUCT_FIELD(u16_t tag);
|
||||
PACK_STRUCT_FIELD(u16_t len);
|
||||
PACK_STRUCT_FIELD(u16_t tag);
|
||||
PACK_STRUCT_FIELD(u16_t len);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
@@ -103,45 +105,71 @@ PACK_STRUCT_END
|
||||
#endif
|
||||
|
||||
|
||||
#define PPPOE_STATE_INITIAL 0
|
||||
#define PPPOE_STATE_PADI_SENT 1
|
||||
#define PPPOE_STATE_PADR_SENT 2
|
||||
#define PPPOE_STATE_SESSION 3
|
||||
#define PPPOE_STATE_CLOSING 4
|
||||
#define PPPOE_STATE_INITIAL 0
|
||||
#define PPPOE_STATE_PADI_SENT 1
|
||||
#define PPPOE_STATE_PADR_SENT 2
|
||||
#define PPPOE_STATE_SESSION 3
|
||||
#define PPPOE_STATE_CLOSING 4
|
||||
/* passive */
|
||||
#define PPPOE_STATE_PADO_SENT 1
|
||||
#define PPPOE_STATE_PADO_SENT 1
|
||||
|
||||
#define PPPOE_HEADERLEN sizeof(struct pppoehdr)
|
||||
#define PPPOE_VERTYPE 0x11 /* VER=1, TYPE = 1 */
|
||||
#define PPPOE_HEADERLEN sizeof(struct pppoehdr)
|
||||
#define PPPOE_VERTYPE 0x11 /* VER=1, TYPE = 1 */
|
||||
|
||||
#define PPPOE_TAG_EOL 0x0000 /* end of list */
|
||||
#define PPPOE_TAG_SNAME 0x0101 /* service name */
|
||||
#define PPPOE_TAG_ACNAME 0x0102 /* access concentrator name */
|
||||
#define PPPOE_TAG_HUNIQUE 0x0103 /* host unique */
|
||||
#define PPPOE_TAG_ACCOOKIE 0x0104 /* AC cookie */
|
||||
#define PPPOE_TAG_VENDOR 0x0105 /* vendor specific */
|
||||
#define PPPOE_TAG_RELAYSID 0x0110 /* relay session id */
|
||||
#define PPPOE_TAG_SNAME_ERR 0x0201 /* service name error */
|
||||
#define PPPOE_TAG_ACSYS_ERR 0x0202 /* AC system error */
|
||||
#define PPPOE_TAG_GENERIC_ERR 0x0203 /* gerneric error */
|
||||
#define PPPOE_TAG_EOL 0x0000 /* end of list */
|
||||
#define PPPOE_TAG_SNAME 0x0101 /* service name */
|
||||
#define PPPOE_TAG_ACNAME 0x0102 /* access concentrator name */
|
||||
#define PPPOE_TAG_HUNIQUE 0x0103 /* host unique */
|
||||
#define PPPOE_TAG_ACCOOKIE 0x0104 /* AC cookie */
|
||||
#define PPPOE_TAG_VENDOR 0x0105 /* vendor specific */
|
||||
#define PPPOE_TAG_RELAYSID 0x0110 /* relay session id */
|
||||
#define PPPOE_TAG_SNAME_ERR 0x0201 /* service name error */
|
||||
#define PPPOE_TAG_ACSYS_ERR 0x0202 /* AC system error */
|
||||
#define PPPOE_TAG_GENERIC_ERR 0x0203 /* gerneric error */
|
||||
|
||||
#define PPPOE_CODE_PADI 0x09 /* Active Discovery Initiation */
|
||||
#define PPPOE_CODE_PADO 0x07 /* Active Discovery Offer */
|
||||
#define PPPOE_CODE_PADR 0x19 /* Active Discovery Request */
|
||||
#define PPPOE_CODE_PADS 0x65 /* Active Discovery Session confirmation */
|
||||
#define PPPOE_CODE_PADT 0xA7 /* Active Discovery Terminate */
|
||||
#define PPPOE_CODE_PADI 0x09 /* Active Discovery Initiation */
|
||||
#define PPPOE_CODE_PADO 0x07 /* Active Discovery Offer */
|
||||
#define PPPOE_CODE_PADR 0x19 /* Active Discovery Request */
|
||||
#define PPPOE_CODE_PADS 0x65 /* Active Discovery Session confirmation */
|
||||
#define PPPOE_CODE_PADT 0xA7 /* Active Discovery Terminate */
|
||||
|
||||
#ifndef ETHERMTU
|
||||
#define ETHERMTU 1500
|
||||
#endif
|
||||
|
||||
/* two byte PPP protocol discriminator, then IP data */
|
||||
#define PPPOE_MAXMTU (ETHERMTU-PPPOE_HEADERLEN-2)
|
||||
#define PPPOE_MAXMTU (ETHERMTU-PPPOE_HEADERLEN-2)
|
||||
|
||||
struct pppoe_softc;
|
||||
#ifndef PPPOE_MAX_AC_COOKIE_LEN
|
||||
#define PPPOE_MAX_AC_COOKIE_LEN 64
|
||||
#endif
|
||||
|
||||
struct pppoe_softc {
|
||||
struct pppoe_softc *next;
|
||||
struct netif *sc_ethif; /* ethernet interface we are using */
|
||||
int sc_pd; /* ppp unit number */
|
||||
void (*sc_linkStatusCB)(int pd, int up);
|
||||
|
||||
int sc_state; /* discovery phase or session connected */
|
||||
struct eth_addr sc_dest; /* hardware address of concentrator */
|
||||
u16_t sc_session; /* PPPoE session id */
|
||||
|
||||
#ifdef PPPOE_TODO
|
||||
char *sc_service_name; /* if != NULL: requested name of service */
|
||||
char *sc_concentrator_name; /* if != NULL: requested concentrator id */
|
||||
#endif /* PPPOE_TODO */
|
||||
u8_t sc_ac_cookie[PPPOE_MAX_AC_COOKIE_LEN]; /* content of AC cookie we must echo back */
|
||||
size_t sc_ac_cookie_len; /* length of cookie data */
|
||||
#ifdef PPPOE_SERVER
|
||||
u8_t *sc_hunique; /* content of host unique we must echo back */
|
||||
size_t sc_hunique_len; /* length of host unique */
|
||||
#endif
|
||||
int sc_padi_retried; /* number of PADI retries already done */
|
||||
int sc_padr_retried; /* number of PADR retries already done */
|
||||
};
|
||||
|
||||
|
||||
void pppoe_init(void);
|
||||
#define pppoe_init() /* compatibility define, no initialization needed */
|
||||
|
||||
err_t pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up), struct pppoe_softc **scptr);
|
||||
err_t pppoe_destroy(struct netif *ifp);
|
||||
@@ -154,7 +182,8 @@ void pppoe_data_input(struct netif *netif, struct pbuf *p);
|
||||
|
||||
err_t pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb);
|
||||
|
||||
extern int pppoe_hdrlen;
|
||||
/** used in ppp.c */
|
||||
#define PPPOE_HDRLEN (sizeof(struct eth_hdr) + PPPOE_HEADERLEN)
|
||||
|
||||
#endif /* PPPOE_SUPPORT */
|
||||
|
||||
|
||||
@@ -34,14 +34,44 @@
|
||||
#ifndef __NETIF_SLIPIF_H__
|
||||
#define __NETIF_SLIPIF_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
/** Set this to 1 to start a thread that blocks reading on the serial line
|
||||
* (using sio_read()).
|
||||
*/
|
||||
#ifndef SLIP_USE_RX_THREAD
|
||||
#define SLIP_USE_RX_THREAD !NO_SYS
|
||||
#endif
|
||||
|
||||
/** Set this to 1 to enable functions to pass in RX bytes from ISR context.
|
||||
* If enabled, slipif_received_byte[s]() process incoming bytes and put assembled
|
||||
* packets on a queue, which is fed into lwIP from slipif_poll().
|
||||
* If disabled, slipif_poll() polls the serila line (using sio_tryread()).
|
||||
*/
|
||||
#ifndef SLIP_RX_FROM_ISR
|
||||
#define SLIP_RX_FROM_ISR 0
|
||||
#endif
|
||||
|
||||
/** Set this to 1 (default for SLIP_RX_FROM_ISR) to queue incoming packets
|
||||
* received by slipif_received_byte[s]() as long as PBUF_POOL pbufs are available.
|
||||
* If disabled, packets will be dropped if more than one packet is received.
|
||||
*/
|
||||
#ifndef SLIP_RX_QUEUE
|
||||
#define SLIP_RX_QUEUE SLIP_RX_FROM_ISR
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
err_t slipif_init(struct netif * netif);
|
||||
void slipif_poll(struct netif *netif);
|
||||
#if SLIP_RX_FROM_ISR
|
||||
void slipif_process_rxqueue(struct netif *netif);
|
||||
void slipif_received_byte(struct netif *netif, u8_t data);
|
||||
void slipif_received_bytes(struct netif *netif, u8_t *data, u8_t len);
|
||||
#endif /* SLIP_RX_FROM_ISR */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
/**
|
||||
* @file
|
||||
* This file is a posix wrapper for lwip/netdb.h.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
@@ -25,29 +27,7 @@
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __NETIF_LOOPIF_H__
|
||||
#define __NETIF_LOOPIF_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
|
||||
#define loopif_poll netif_poll
|
||||
#endif /* !LWIP_NETIF_LOOPBACK_MULTITHREADING */
|
||||
|
||||
err_t loopif_init(struct netif *netif);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NETIF_LOOPIF_H__ */
|
||||
#include "lwip/netdb.h"
|
||||
33
src/include/posix/sys/socket.h
Normal file
33
src/include/posix/sys/socket.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* @file
|
||||
* This file is a posix wrapper for lwip/sockets.h.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/sockets.h"
|
||||
1041
src/netif/etharp.c
1041
src/netif/etharp.c
File diff suppressed because it is too large
Load Diff
@@ -50,7 +50,6 @@
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/sys.h"
|
||||
#include <lwip/stats.h>
|
||||
#include <lwip/snmp.h>
|
||||
#include "netif/etharp.h"
|
||||
|
||||
1052
src/netif/ppp/auth.c
1052
src/netif/ppp/auth.c
File diff suppressed because it is too large
Load Diff
@@ -97,7 +97,7 @@ void auth_check_options (void);
|
||||
void auth_reset (int);
|
||||
|
||||
/* Check peer-supplied username/password */
|
||||
int check_passwd (int, char *, int, char *, int, char **, int *);
|
||||
u_char check_passwd (int, char *, int, char *, int, char **, int *);
|
||||
|
||||
/* get "secret" for chap */
|
||||
int get_secret (int, char *, char *, char *, int *, int);
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
|
||||
#if CHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "ppp.h"
|
||||
#include "ppp_impl.h"
|
||||
#include "pppdebug.h"
|
||||
|
||||
#include "magic.h"
|
||||
@@ -84,19 +84,25 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/*************************/
|
||||
/*** LOCAL DEFINITIONS ***/
|
||||
/*************************/
|
||||
#if 0 /* UNUSED */
|
||||
/*
|
||||
* Command-line options.
|
||||
*/
|
||||
static option_t chap_option_list[] = {
|
||||
{ "chap-restart", o_int, &chap[0].timeouttime,
|
||||
"Set timeout for CHAP" },
|
||||
{ "chap-max-challenge", o_int, &chap[0].max_transmits,
|
||||
"Set max #xmits for challenge" },
|
||||
{ "chap-interval", o_int, &chap[0].chal_interval,
|
||||
"Set interval for rechallenge" },
|
||||
#ifdef MSLANMAN
|
||||
{ "ms-lanman", o_bool, &ms_lanman,
|
||||
"Use LanMan passwd when using MS-CHAP", 1 },
|
||||
#endif
|
||||
{ NULL }
|
||||
};
|
||||
#endif /* UNUSED */
|
||||
|
||||
|
||||
/************************/
|
||||
/*** LOCAL DATA TYPES ***/
|
||||
/************************/
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** LOCAL FUNCTION DECLARATIONS ***/
|
||||
/***********************************/
|
||||
/*
|
||||
* Protocol entry points.
|
||||
*/
|
||||
@@ -105,28 +111,10 @@ static void ChapLowerUp (int);
|
||||
static void ChapLowerDown (int);
|
||||
static void ChapInput (int, u_char *, int);
|
||||
static void ChapProtocolReject (int);
|
||||
#if 0
|
||||
#if PPP_ADDITIONAL_CALLBACKS
|
||||
static int ChapPrintPkt (u_char *, int, void (*) (void *, char *, ...), void *);
|
||||
#endif
|
||||
|
||||
static void ChapChallengeTimeout (void *);
|
||||
static void ChapResponseTimeout (void *);
|
||||
static void ChapReceiveChallenge (chap_state *, u_char *, int, int);
|
||||
static void ChapRechallenge (void *);
|
||||
static void ChapReceiveResponse (chap_state *, u_char *, int, int);
|
||||
static void ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len);
|
||||
static void ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len);
|
||||
static void ChapSendStatus (chap_state *, int);
|
||||
static void ChapSendChallenge (chap_state *);
|
||||
static void ChapSendResponse (chap_state *);
|
||||
static void ChapGenChallenge (chap_state *);
|
||||
|
||||
|
||||
/******************************/
|
||||
/*** PUBLIC DATA STRUCTURES ***/
|
||||
/******************************/
|
||||
chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */
|
||||
|
||||
struct protent chap_protent = {
|
||||
PPP_CHAP,
|
||||
ChapInit,
|
||||
@@ -136,29 +124,57 @@ struct protent chap_protent = {
|
||||
ChapLowerDown,
|
||||
NULL,
|
||||
NULL,
|
||||
#if 0
|
||||
#if PPP_ADDITIONAL_CALLBACKS
|
||||
ChapPrintPkt,
|
||||
NULL,
|
||||
#endif
|
||||
#endif /* PPP_ADDITIONAL_CALLBACKS */
|
||||
1,
|
||||
"CHAP",
|
||||
#if 0
|
||||
#if PPP_ADDITIONAL_CALLBACKS
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
#endif
|
||||
#endif /* PPP_ADDITIONAL_CALLBACKS */
|
||||
};
|
||||
|
||||
chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */
|
||||
|
||||
static void ChapChallengeTimeout (void *);
|
||||
static void ChapResponseTimeout (void *);
|
||||
static void ChapReceiveChallenge (chap_state *, u_char *, u_char, int);
|
||||
static void ChapRechallenge (void *);
|
||||
static void ChapReceiveResponse (chap_state *, u_char *, int, int);
|
||||
static void ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len);
|
||||
static void ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len);
|
||||
static void ChapSendStatus (chap_state *, int);
|
||||
static void ChapSendChallenge (chap_state *);
|
||||
static void ChapSendResponse (chap_state *);
|
||||
static void ChapGenChallenge (chap_state *);
|
||||
|
||||
/*
|
||||
* ChapInit - Initialize a CHAP unit.
|
||||
*/
|
||||
static void
|
||||
ChapInit(int unit)
|
||||
{
|
||||
chap_state *cstate = &chap[unit];
|
||||
|
||||
BZERO(cstate, sizeof(*cstate));
|
||||
cstate->unit = unit;
|
||||
cstate->clientstate = CHAPCS_INITIAL;
|
||||
cstate->serverstate = CHAPSS_INITIAL;
|
||||
cstate->timeouttime = CHAP_DEFTIMEOUT;
|
||||
cstate->max_transmits = CHAP_DEFTRANSMITS;
|
||||
/* random number generator is initialized in magic_init */
|
||||
}
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** PUBLIC FUNCTION DEFINITIONS ***/
|
||||
/***********************************/
|
||||
/*
|
||||
* ChapAuthWithPeer - Authenticate us with our peer (start client).
|
||||
*
|
||||
*/
|
||||
void
|
||||
ChapAuthWithPeer(int unit, char *our_name, int digest)
|
||||
ChapAuthWithPeer(int unit, char *our_name, u_char digest)
|
||||
{
|
||||
chap_state *cstate = &chap[unit];
|
||||
|
||||
@@ -185,7 +201,7 @@ ChapAuthWithPeer(int unit, char *our_name, int digest)
|
||||
* ChapAuthPeer - Authenticate our peer (start server).
|
||||
*/
|
||||
void
|
||||
ChapAuthPeer(int unit, char *our_name, int digest)
|
||||
ChapAuthPeer(int unit, char *our_name, u_char digest)
|
||||
{
|
||||
chap_state *cstate = &chap[unit];
|
||||
|
||||
@@ -205,27 +221,6 @@ ChapAuthPeer(int unit, char *our_name, int digest)
|
||||
}
|
||||
|
||||
|
||||
/**********************************/
|
||||
/*** LOCAL FUNCTION DEFINITIONS ***/
|
||||
/**********************************/
|
||||
/*
|
||||
* ChapInit - Initialize a CHAP unit.
|
||||
*/
|
||||
static void
|
||||
ChapInit(int unit)
|
||||
{
|
||||
chap_state *cstate = &chap[unit];
|
||||
|
||||
BZERO(cstate, sizeof(*cstate));
|
||||
cstate->unit = unit;
|
||||
cstate->clientstate = CHAPCS_INITIAL;
|
||||
cstate->serverstate = CHAPSS_INITIAL;
|
||||
cstate->timeouttime = CHAP_DEFTIMEOUT;
|
||||
cstate->max_transmits = CHAP_DEFTRANSMITS;
|
||||
/* random number generator is initialized in magic_init */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ChapChallengeTimeout - Timeout expired on sending challenge.
|
||||
*/
|
||||
@@ -243,7 +238,7 @@ ChapChallengeTimeout(void *arg)
|
||||
|
||||
if (cstate->chal_transmits >= cstate->max_transmits) {
|
||||
/* give up on peer */
|
||||
CHAPDEBUG((LOG_ERR, "Peer failed to respond to CHAP challenge\n"));
|
||||
CHAPDEBUG(LOG_ERR, ("Peer failed to respond to CHAP challenge\n"));
|
||||
cstate->serverstate = CHAPSS_BADAUTH;
|
||||
auth_peer_fail(cstate->unit, PPP_CHAP);
|
||||
return;
|
||||
@@ -355,7 +350,7 @@ ChapProtocolReject(int unit)
|
||||
}
|
||||
if (cstate->clientstate != CHAPCS_INITIAL &&
|
||||
cstate->clientstate != CHAPCS_CLOSED) {
|
||||
auth_withpeer_fail(unit, PPP_CHAP);
|
||||
auth_withpeer_fail(unit, PPP_CHAP); /* lwip: just sets the PPP error code on this unit to PPPERR_AUTHFAIL */
|
||||
}
|
||||
ChapLowerDown(unit); /* shutdown chap */
|
||||
}
|
||||
@@ -378,18 +373,18 @@ ChapInput(int unit, u_char *inpacket, int packet_len)
|
||||
*/
|
||||
inp = inpacket;
|
||||
if (packet_len < CHAP_HEADERLEN) {
|
||||
CHAPDEBUG((LOG_INFO, "ChapInput: rcvd short header.\n"));
|
||||
CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd short header.\n"));
|
||||
return;
|
||||
}
|
||||
GETCHAR(code, inp);
|
||||
GETCHAR(id, inp);
|
||||
GETSHORT(len, inp);
|
||||
if (len < CHAP_HEADERLEN) {
|
||||
CHAPDEBUG((LOG_INFO, "ChapInput: rcvd illegal length.\n"));
|
||||
CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd illegal length.\n"));
|
||||
return;
|
||||
}
|
||||
if (len > packet_len) {
|
||||
CHAPDEBUG((LOG_INFO, "ChapInput: rcvd short packet.\n"));
|
||||
CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
len -= CHAP_HEADERLEN;
|
||||
@@ -415,7 +410,7 @@ ChapInput(int unit, u_char *inpacket, int packet_len)
|
||||
break;
|
||||
|
||||
default: /* Need code reject? */
|
||||
CHAPDEBUG((LOG_WARNING, "Unknown CHAP code (%d) received.\n", code));
|
||||
CHAPDEBUG(LOG_WARNING, ("Unknown CHAP code (%d) received.\n", code));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -425,7 +420,7 @@ ChapInput(int unit, u_char *inpacket, int packet_len)
|
||||
* ChapReceiveChallenge - Receive Challenge and send Response.
|
||||
*/
|
||||
static void
|
||||
ChapReceiveChallenge(chap_state *cstate, u_char *inp, int id, int len)
|
||||
ChapReceiveChallenge(chap_state *cstate, u_char *inp, u_char id, int len)
|
||||
{
|
||||
int rchallenge_len;
|
||||
u_char *rchallenge;
|
||||
@@ -434,48 +429,52 @@ ChapReceiveChallenge(chap_state *cstate, u_char *inp, int id, int len)
|
||||
char rhostname[256];
|
||||
MD5_CTX mdContext;
|
||||
u_char hash[MD5_SIGNATURE_SIZE];
|
||||
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: Rcvd id %d.\n", id));
|
||||
|
||||
CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: Rcvd id %d.\n", id));
|
||||
if (cstate->clientstate == CHAPCS_CLOSED ||
|
||||
cstate->clientstate == CHAPCS_PENDING) {
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: in state %d\n",
|
||||
CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: in state %d\n",
|
||||
cstate->clientstate));
|
||||
return;
|
||||
}
|
||||
|
||||
if (len < 2) {
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: rcvd short packet.\n"));
|
||||
CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
GETCHAR(rchallenge_len, inp);
|
||||
len -= sizeof (u_char) + rchallenge_len; /* now name field length */
|
||||
if (len < 0) {
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: rcvd short packet.\n"));
|
||||
CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
rchallenge = inp;
|
||||
INCPTR(rchallenge_len, inp);
|
||||
|
||||
if (len >= sizeof(rhostname)) {
|
||||
if (len >= (int)sizeof(rhostname)) {
|
||||
len = sizeof(rhostname) - 1;
|
||||
}
|
||||
BCOPY(inp, rhostname, len);
|
||||
rhostname[len] = '\000';
|
||||
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: received name field '%s'\n", rhostname));
|
||||
CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: received name field '%s'\n",
|
||||
rhostname));
|
||||
|
||||
/* Microsoft doesn't send their name back in the PPP packet */
|
||||
if (ppp_settings.remote_name[0] != 0 && (ppp_settings.explicit_remote || rhostname[0] == 0)) {
|
||||
strncpy(rhostname, ppp_settings.remote_name, sizeof(rhostname));
|
||||
rhostname[sizeof(rhostname) - 1] = 0;
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: using '%s' as remote name\n", rhostname));
|
||||
CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: using '%s' as remote name\n",
|
||||
rhostname));
|
||||
}
|
||||
|
||||
/* get secret for authenticating ourselves with the specified host */
|
||||
if (!get_secret(cstate->unit, cstate->resp_name, rhostname, secret, &secret_len, 0)) {
|
||||
if (!get_secret(cstate->unit, cstate->resp_name, rhostname,
|
||||
secret, &secret_len, 0)) {
|
||||
secret_len = 0; /* assume null secret if can't find one */
|
||||
CHAPDEBUG((LOG_WARNING, "No CHAP secret found for authenticating us to %s\n", rhostname));
|
||||
CHAPDEBUG(LOG_WARNING, ("No CHAP secret found for authenticating us to %s\n",
|
||||
rhostname));
|
||||
}
|
||||
|
||||
/* cancel response send timeout if necessary */
|
||||
@@ -499,14 +498,14 @@ ChapReceiveChallenge(chap_state *cstate, u_char *inp, int id, int len)
|
||||
cstate->resp_length = MD5_SIGNATURE_SIZE;
|
||||
break;
|
||||
|
||||
#ifdef CHAPMS
|
||||
#if MSCHAP_SUPPORT
|
||||
case CHAP_MICROSOFT:
|
||||
ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
CHAPDEBUG((LOG_INFO, "unknown digest type %d\n", cstate->resp_type));
|
||||
CHAPDEBUG(LOG_INFO, ("unknown digest type %d\n", cstate->resp_type));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -528,12 +527,12 @@ ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len)
|
||||
MD5_CTX mdContext;
|
||||
char secret[MAXSECRETLEN];
|
||||
u_char hash[MD5_SIGNATURE_SIZE];
|
||||
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: Rcvd id %d.\n", id));
|
||||
|
||||
CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: Rcvd id %d.\n", id));
|
||||
|
||||
if (cstate->serverstate == CHAPSS_CLOSED ||
|
||||
cstate->serverstate == CHAPSS_PENDING) {
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: in state %d\n",
|
||||
CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: in state %d\n",
|
||||
cstate->serverstate));
|
||||
return;
|
||||
}
|
||||
@@ -557,7 +556,7 @@ ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len)
|
||||
}
|
||||
|
||||
if (len < 2) {
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: rcvd short packet.\n"));
|
||||
CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
GETCHAR(remmd_len, inp); /* get length of MD */
|
||||
@@ -566,29 +565,30 @@ ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len)
|
||||
|
||||
len -= sizeof (u_char) + remmd_len;
|
||||
if (len < 0) {
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: rcvd short packet.\n"));
|
||||
CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
UNTIMEOUT(ChapChallengeTimeout, cstate);
|
||||
|
||||
if (len >= sizeof(rhostname)) {
|
||||
if (len >= (int)sizeof(rhostname)) {
|
||||
len = sizeof(rhostname) - 1;
|
||||
}
|
||||
BCOPY(inp, rhostname, len);
|
||||
rhostname[len] = '\000';
|
||||
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: received name field: %s\n", rhostname));
|
||||
CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: received name field: %s\n",
|
||||
rhostname));
|
||||
|
||||
/*
|
||||
* Get secret for authenticating them with us,
|
||||
* do the hash ourselves, and compare the result.
|
||||
*/
|
||||
code = CHAP_FAILURE;
|
||||
if (!get_secret(cstate->unit, rhostname, cstate->chal_name, secret, &secret_len, 1)) {
|
||||
/* CHAPDEBUG((LOG_WARNING, TL_CHAP, "No CHAP secret found for authenticating %s\n", rhostname)); */
|
||||
CHAPDEBUG((LOG_WARNING, "No CHAP secret found for authenticating %s\n",
|
||||
rhostname));
|
||||
if (!get_secret(cstate->unit, rhostname, cstate->chal_name,
|
||||
secret, &secret_len, 1)) {
|
||||
CHAPDEBUG(LOG_WARNING, ("No CHAP secret found for authenticating %s\n",
|
||||
rhostname));
|
||||
} else {
|
||||
/* generate MD based on negotiated type */
|
||||
switch (cstate->chal_type) {
|
||||
@@ -610,7 +610,7 @@ ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len)
|
||||
break;
|
||||
|
||||
default:
|
||||
CHAPDEBUG((LOG_INFO, "unknown digest type %d\n", cstate->chal_type));
|
||||
CHAPDEBUG(LOG_INFO, ("unknown digest type %d\n", cstate->chal_type));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -627,7 +627,7 @@ ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len)
|
||||
TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval);
|
||||
}
|
||||
} else {
|
||||
CHAPDEBUG((LOG_ERR, "CHAP peer authentication failed\n"));
|
||||
CHAPDEBUG(LOG_ERR, ("CHAP peer authentication failed\n"));
|
||||
cstate->serverstate = CHAPSS_BADAUTH;
|
||||
auth_peer_fail(cstate->unit, PPP_CHAP);
|
||||
}
|
||||
@@ -642,7 +642,7 @@ ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len)
|
||||
LWIP_UNUSED_ARG(id);
|
||||
LWIP_UNUSED_ARG(inp);
|
||||
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveSuccess: Rcvd id %d.\n", id));
|
||||
CHAPDEBUG(LOG_INFO, ("ChapReceiveSuccess: Rcvd id %d.\n", id));
|
||||
|
||||
if (cstate->clientstate == CHAPCS_OPEN) {
|
||||
/* presumably an answer to a duplicate response */
|
||||
@@ -651,7 +651,8 @@ ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len)
|
||||
|
||||
if (cstate->clientstate != CHAPCS_RESPONSE) {
|
||||
/* don't know what this is */
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveSuccess: in state %d\n", cstate->clientstate));
|
||||
CHAPDEBUG(LOG_INFO, ("ChapReceiveSuccess: in state %d\n",
|
||||
cstate->clientstate));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -679,11 +680,12 @@ ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len)
|
||||
LWIP_UNUSED_ARG(id);
|
||||
LWIP_UNUSED_ARG(inp);
|
||||
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveFailure: Rcvd id %d.\n", id));
|
||||
CHAPDEBUG(LOG_INFO, ("ChapReceiveFailure: Rcvd id %d.\n", id));
|
||||
|
||||
if (cstate->clientstate != CHAPCS_RESPONSE) {
|
||||
/* don't know what this is */
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveFailure: in state %d\n", cstate->clientstate));
|
||||
CHAPDEBUG(LOG_INFO, ("ChapReceiveFailure: in state %d\n",
|
||||
cstate->clientstate));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -696,8 +698,8 @@ ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len)
|
||||
PRINTMSG(inp, len);
|
||||
}
|
||||
|
||||
CHAPDEBUG((LOG_ERR, "CHAP authentication failed\n"));
|
||||
auth_withpeer_fail(cstate->unit, PPP_CHAP);
|
||||
CHAPDEBUG(LOG_ERR, ("CHAP authentication failed\n"));
|
||||
auth_withpeer_fail(cstate->unit, PPP_CHAP); /* lwip: just sets the PPP error code on this unit to PPPERR_AUTHFAIL */
|
||||
}
|
||||
|
||||
|
||||
@@ -712,25 +714,25 @@ ChapSendChallenge(chap_state *cstate)
|
||||
int outlen;
|
||||
|
||||
chal_len = cstate->chal_len;
|
||||
name_len = strlen(cstate->chal_name);
|
||||
name_len = (int)strlen(cstate->chal_name);
|
||||
outlen = CHAP_HEADERLEN + sizeof (u_char) + chal_len + name_len;
|
||||
outp = outpacket_buf[cstate->unit];
|
||||
|
||||
|
||||
MAKEHEADER(outp, PPP_CHAP); /* paste in a CHAP header */
|
||||
|
||||
|
||||
PUTCHAR(CHAP_CHALLENGE, outp);
|
||||
PUTCHAR(cstate->chal_id, outp);
|
||||
PUTSHORT(outlen, outp);
|
||||
|
||||
|
||||
PUTCHAR(chal_len, outp); /* put length of challenge */
|
||||
BCOPY(cstate->challenge, outp, chal_len);
|
||||
INCPTR(chal_len, outp);
|
||||
|
||||
|
||||
BCOPY(cstate->chal_name, outp, name_len); /* append hostname */
|
||||
|
||||
pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
|
||||
|
||||
CHAPDEBUG((LOG_INFO, "ChapSendChallenge: Sent id %d.\n", cstate->chal_id));
|
||||
|
||||
CHAPDEBUG(LOG_INFO, ("ChapSendChallenge: Sent id %d.\n", cstate->chal_id));
|
||||
|
||||
TIMEOUT(ChapChallengeTimeout, cstate, cstate->timeouttime);
|
||||
++cstate->chal_transmits;
|
||||
@@ -745,18 +747,18 @@ ChapSendStatus(chap_state *cstate, int code)
|
||||
{
|
||||
u_char *outp;
|
||||
int outlen, msglen;
|
||||
char msg[256];
|
||||
|
||||
char msg[256]; /* @todo: this can be a char*, no strcpy needed */
|
||||
|
||||
if (code == CHAP_SUCCESS) {
|
||||
strcpy(msg, "Welcome!");
|
||||
} else {
|
||||
strcpy(msg, "I don't like you. Go 'way.");
|
||||
}
|
||||
msglen = strlen(msg);
|
||||
|
||||
msglen = (int)strlen(msg);
|
||||
|
||||
outlen = CHAP_HEADERLEN + msglen;
|
||||
outp = outpacket_buf[cstate->unit];
|
||||
|
||||
|
||||
MAKEHEADER(outp, PPP_CHAP); /* paste in a header */
|
||||
|
||||
PUTCHAR(code, outp);
|
||||
@@ -764,8 +766,9 @@ ChapSendStatus(chap_state *cstate, int code)
|
||||
PUTSHORT(outlen, outp);
|
||||
BCOPY(msg, outp, msglen);
|
||||
pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
|
||||
|
||||
CHAPDEBUG((LOG_INFO, "ChapSendStatus: Sent code %d, id %d.\n", code, cstate->chal_id));
|
||||
|
||||
CHAPDEBUG(LOG_INFO, ("ChapSendStatus: Sent code %d, id %d.\n", code,
|
||||
cstate->chal_id));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -781,17 +784,18 @@ ChapGenChallenge(chap_state *cstate)
|
||||
int chal_len;
|
||||
u_char *ptr = cstate->challenge;
|
||||
int i;
|
||||
|
||||
|
||||
/* pick a random challenge length between MIN_CHALLENGE_LENGTH and
|
||||
MAX_CHALLENGE_LENGTH */
|
||||
chal_len = (unsigned)
|
||||
((((magic() >> 16) *
|
||||
(MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) >> 16)
|
||||
+ MIN_CHALLENGE_LENGTH);
|
||||
cstate->chal_len = chal_len;
|
||||
LWIP_ASSERT("chal_len <= 0xff", chal_len <= 0xffff);
|
||||
cstate->chal_len = (u_char)chal_len;
|
||||
cstate->chal_id = ++cstate->id;
|
||||
cstate->chal_transmits = 0;
|
||||
|
||||
|
||||
/* generate a random string */
|
||||
for (i = 0; i < chal_len; i++ ) {
|
||||
*ptr++ = (char) (magic() & 0xff);
|
||||
@@ -808,12 +812,12 @@ ChapSendResponse(chap_state *cstate)
|
||||
{
|
||||
u_char *outp;
|
||||
int outlen, md_len, name_len;
|
||||
|
||||
|
||||
md_len = cstate->resp_length;
|
||||
name_len = strlen(cstate->resp_name);
|
||||
name_len = (int)strlen(cstate->resp_name);
|
||||
outlen = CHAP_HEADERLEN + sizeof (u_char) + md_len + name_len;
|
||||
outp = outpacket_buf[cstate->unit];
|
||||
|
||||
|
||||
MAKEHEADER(outp, PPP_CHAP);
|
||||
|
||||
PUTCHAR(CHAP_RESPONSE, outp); /* we are a response */
|
||||
@@ -823,18 +827,18 @@ ChapSendResponse(chap_state *cstate)
|
||||
PUTCHAR(md_len, outp); /* length of MD */
|
||||
BCOPY(cstate->response, outp, md_len); /* copy MD to buffer */
|
||||
INCPTR(md_len, outp);
|
||||
|
||||
|
||||
BCOPY(cstate->resp_name, outp, name_len); /* append our name */
|
||||
|
||||
|
||||
/* send the packet */
|
||||
pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
|
||||
|
||||
|
||||
cstate->clientstate = CHAPCS_RESPONSE;
|
||||
TIMEOUT(ChapResponseTimeout, cstate, cstate->timeouttime);
|
||||
++cstate->resp_transmits;
|
||||
}
|
||||
|
||||
#if 0
|
||||
#if PPP_ADDITIONAL_CALLBACKS
|
||||
static char *ChapCodenames[] = {
|
||||
"Challenge", "Response", "Success", "Failure"
|
||||
};
|
||||
@@ -847,7 +851,7 @@ ChapPrintPkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void *
|
||||
int code, id, len;
|
||||
int clen, nlen;
|
||||
u_char x;
|
||||
|
||||
|
||||
if (plen < CHAP_HEADERLEN) {
|
||||
return 0;
|
||||
}
|
||||
@@ -857,6 +861,7 @@ ChapPrintPkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void *
|
||||
if (len < CHAP_HEADERLEN || len > plen) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (code >= 1 && code <= sizeof(ChapCodenames) / sizeof(char *)) {
|
||||
printer(arg, " %s", ChapCodenames[code-1]);
|
||||
} else {
|
||||
@@ -896,7 +901,7 @@ ChapPrintPkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void *
|
||||
|
||||
return len + CHAP_HEADERLEN;
|
||||
}
|
||||
#endif
|
||||
#endif /* PPP_ADDITIONAL_CALLBACKS */
|
||||
|
||||
#endif /* CHAP_SUPPORT */
|
||||
|
||||
|
||||
@@ -62,16 +62,12 @@
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id: chap.h,v 1.4 2007/12/19 20:47:22 fbernon Exp $
|
||||
* $Id: chap.h,v 1.6 2010/01/24 13:19:34 goldsimon Exp $
|
||||
*/
|
||||
|
||||
#ifndef CHAP_H
|
||||
#define CHAP_H
|
||||
|
||||
/*************************
|
||||
*** PUBLIC DEFINITIONS ***
|
||||
*************************/
|
||||
|
||||
/* Code + ID + length */
|
||||
#define CHAP_HEADERLEN 4
|
||||
|
||||
@@ -96,31 +92,6 @@
|
||||
#define MAX_CHALLENGE_LENGTH 64
|
||||
#define MAX_RESPONSE_LENGTH 64 /* sufficient for MD5 or MS-CHAP */
|
||||
|
||||
/*
|
||||
* Client (peer) states.
|
||||
*/
|
||||
#define CHAPCS_INITIAL 0 /* Lower layer down, not opened */
|
||||
#define CHAPCS_CLOSED 1 /* Lower layer up, not opened */
|
||||
#define CHAPCS_PENDING 2 /* Auth us to peer when lower up */
|
||||
#define CHAPCS_LISTEN 3 /* Listening for a challenge */
|
||||
#define CHAPCS_RESPONSE 4 /* Sent response, waiting for status */
|
||||
#define CHAPCS_OPEN 5 /* We've received Success */
|
||||
|
||||
/*
|
||||
* Server (authenticator) states.
|
||||
*/
|
||||
#define CHAPSS_INITIAL 0 /* Lower layer down, not opened */
|
||||
#define CHAPSS_CLOSED 1 /* Lower layer up, not opened */
|
||||
#define CHAPSS_PENDING 2 /* Auth peer when lower up */
|
||||
#define CHAPSS_INITIAL_CHAL 3 /* We've sent the first challenge */
|
||||
#define CHAPSS_OPEN 4 /* We've sent a Success msg */
|
||||
#define CHAPSS_RECHALLENGE 5 /* We've sent another challenge */
|
||||
#define CHAPSS_BADAUTH 6 /* We've sent a Failure msg */
|
||||
|
||||
/************************
|
||||
*** PUBLIC DATA TYPES ***
|
||||
************************/
|
||||
|
||||
/*
|
||||
* Each interface is described by a chap structure.
|
||||
*/
|
||||
@@ -148,19 +119,32 @@ typedef struct chap_state {
|
||||
} chap_state;
|
||||
|
||||
|
||||
/******************
|
||||
*** PUBLIC DATA ***
|
||||
******************/
|
||||
/*
|
||||
* Client (peer) states.
|
||||
*/
|
||||
#define CHAPCS_INITIAL 0 /* Lower layer down, not opened */
|
||||
#define CHAPCS_CLOSED 1 /* Lower layer up, not opened */
|
||||
#define CHAPCS_PENDING 2 /* Auth us to peer when lower up */
|
||||
#define CHAPCS_LISTEN 3 /* Listening for a challenge */
|
||||
#define CHAPCS_RESPONSE 4 /* Sent response, waiting for status */
|
||||
#define CHAPCS_OPEN 5 /* We've received Success */
|
||||
|
||||
/*
|
||||
* Server (authenticator) states.
|
||||
*/
|
||||
#define CHAPSS_INITIAL 0 /* Lower layer down, not opened */
|
||||
#define CHAPSS_CLOSED 1 /* Lower layer up, not opened */
|
||||
#define CHAPSS_PENDING 2 /* Auth peer when lower up */
|
||||
#define CHAPSS_INITIAL_CHAL 3 /* We've sent the first challenge */
|
||||
#define CHAPSS_OPEN 4 /* We've sent a Success msg */
|
||||
#define CHAPSS_RECHALLENGE 5 /* We've sent another challenge */
|
||||
#define CHAPSS_BADAUTH 6 /* We've sent a Failure msg */
|
||||
|
||||
extern chap_state chap[];
|
||||
|
||||
void ChapAuthWithPeer (int, char *, u_char);
|
||||
void ChapAuthPeer (int, char *, u_char);
|
||||
|
||||
extern struct protent chap_protent;
|
||||
|
||||
|
||||
/***********************
|
||||
*** PUBLIC FUNCTIONS ***
|
||||
***********************/
|
||||
|
||||
void ChapAuthWithPeer (int, char *, int);
|
||||
void ChapAuthPeer (int, char *, int);
|
||||
|
||||
#endif /* CHAP_H */
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
|
||||
#if MSCHAP_SUPPORT /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "ppp.h"
|
||||
#include "ppp_impl.h"
|
||||
#include "pppdebug.h"
|
||||
|
||||
#include "md4.h"
|
||||
@@ -85,6 +85,8 @@
|
||||
#include "chap.h"
|
||||
#include "chpms.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/*************************/
|
||||
/*** LOCAL DEFINITIONS ***/
|
||||
@@ -137,49 +139,12 @@ static u_char Get7Bits(
|
||||
int startBit
|
||||
);
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** PUBLIC FUNCTION DEFINITIONS ***/
|
||||
/***********************************/
|
||||
void
|
||||
ChapMS( chap_state *cstate, char *rchallenge, int rchallenge_len, char *secret, int secret_len)
|
||||
{
|
||||
MS_ChapResponse response;
|
||||
#ifdef MSLANMAN
|
||||
extern int ms_lanman;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
CHAPDEBUG((LOG_INFO, "ChapMS: secret is '%.*s'\n", secret_len, secret));
|
||||
#endif
|
||||
BZERO(&response, sizeof(response));
|
||||
|
||||
/* Calculate both always */
|
||||
ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, &response);
|
||||
|
||||
#ifdef MSLANMAN
|
||||
ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, &response);
|
||||
|
||||
/* prefered method is set by option */
|
||||
response.UseNT = !ms_lanman;
|
||||
#else
|
||||
response.UseNT = 1;
|
||||
#endif
|
||||
|
||||
BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN);
|
||||
cstate->resp_length = MS_CHAP_RESPONSE_LEN;
|
||||
}
|
||||
|
||||
|
||||
/**********************************/
|
||||
/*** LOCAL FUNCTION DEFINITIONS ***/
|
||||
/**********************************/
|
||||
static void
|
||||
ChallengeResponse( u_char *challenge, /* IN 8 octets */
|
||||
u_char *pwHash, /* IN 16 octets */
|
||||
u_char *response /* OUT 24 octets */)
|
||||
{
|
||||
char ZPasswordHash[21];
|
||||
u_char ZPasswordHash[21];
|
||||
|
||||
BZERO(ZPasswordHash, sizeof(ZPasswordHash));
|
||||
BCOPY(pwHash, ZPasswordHash, 16);
|
||||
@@ -211,19 +176,19 @@ DesEncrypt( u_char *clear, /* IN 8 octets */
|
||||
MakeKey(key, des_key);
|
||||
|
||||
Expand(des_key, crypt_key);
|
||||
setkey(crypt_key);
|
||||
setkey((char*)crypt_key);
|
||||
|
||||
#if 0
|
||||
CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||
CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||
clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7]));
|
||||
#endif
|
||||
|
||||
Expand(clear, des_input);
|
||||
encrypt(des_input, 0);
|
||||
encrypt((char*)des_input, 0);
|
||||
Collapse(des_input, cipher);
|
||||
|
||||
#if 0
|
||||
CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||
CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||
cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7]));
|
||||
#endif
|
||||
}
|
||||
@@ -243,14 +208,14 @@ DesEncrypt( u_char *clear, /* IN 8 octets */
|
||||
des_set_key(&des_key, key_schedule);
|
||||
|
||||
#if 0
|
||||
CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||
CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||
clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7]));
|
||||
#endif
|
||||
|
||||
des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1);
|
||||
|
||||
#if 0
|
||||
CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||
CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||
cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7]));
|
||||
#endif
|
||||
}
|
||||
@@ -329,9 +294,9 @@ MakeKey( u_char *key, /* IN 56 bit DES key missing parity bits */
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
CHAPDEBUG((LOG_INFO, "MakeKey: 56-bit input : %02X%02X%02X%02X%02X%02X%02X\n",
|
||||
CHAPDEBUG(LOG_INFO, ("MakeKey: 56-bit input : %02X%02X%02X%02X%02X%02X%02X\n",
|
||||
key[0], key[1], key[2], key[3], key[4], key[5], key[6]));
|
||||
CHAPDEBUG((LOG_INFO, "MakeKey: 64-bit output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||
CHAPDEBUG(LOG_INFO, ("MakeKey: 64-bit output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||
des_key[0], des_key[1], des_key[2], des_key[3], des_key[4], des_key[5], des_key[6], des_key[7]));
|
||||
#endif
|
||||
}
|
||||
@@ -348,6 +313,8 @@ ChapMS_NT( char *rchallenge,
|
||||
u_char unicodePassword[MAX_NT_PASSWORD * 2];
|
||||
static int low_byte_first = -1;
|
||||
|
||||
LWIP_UNUSED_ARG(rchallenge_len);
|
||||
|
||||
/* Initialize the Unicode version of the secret (== password). */
|
||||
/* This implicitly supports 8-bit ISO8859/1 characters. */
|
||||
BZERO(unicodePassword, sizeof(unicodePassword));
|
||||
@@ -358,15 +325,16 @@ ChapMS_NT( char *rchallenge,
|
||||
MDupdate(&md4Context, unicodePassword, secret_len * 2 * 8); /* Unicode is 2 bytes/char, *8 for bit count */
|
||||
|
||||
if (low_byte_first == -1) {
|
||||
low_byte_first = (htons((unsigned short int)1) != 1);
|
||||
low_byte_first = (PP_HTONS((unsigned short int)1) != 1);
|
||||
}
|
||||
if (low_byte_first == 0) {
|
||||
MDreverse((u_long *)&md4Context); /* sfb 961105 */
|
||||
/* @todo: arg type - u_long* or u_int* ? */
|
||||
MDreverse((unsigned int*)&md4Context); /* sfb 961105 */
|
||||
}
|
||||
|
||||
MDupdate(&md4Context, NULL, 0); /* Tell MD4 we're done */
|
||||
|
||||
ChallengeResponse(rchallenge, (char *)md4Context.buffer, response->NTResp);
|
||||
ChallengeResponse((u_char*)rchallenge, (u_char*)md4Context.buffer, response->NTResp);
|
||||
}
|
||||
|
||||
#ifdef MSLANMAN
|
||||
@@ -394,6 +362,35 @@ ChapMS_LANMan( char *rchallenge,
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
ChapMS( chap_state *cstate, char *rchallenge, int rchallenge_len, char *secret, int secret_len)
|
||||
{
|
||||
MS_ChapResponse response;
|
||||
#ifdef MSLANMAN
|
||||
extern int ms_lanman;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
CHAPDEBUG(LOG_INFO, ("ChapMS: secret is '%.*s'\n", secret_len, secret));
|
||||
#endif
|
||||
BZERO(&response, sizeof(response));
|
||||
|
||||
/* Calculate both always */
|
||||
ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, &response);
|
||||
|
||||
#ifdef MSLANMAN
|
||||
ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, &response);
|
||||
|
||||
/* prefered method is set by option */
|
||||
response.UseNT = !ms_lanman;
|
||||
#else
|
||||
response.UseNT = 1;
|
||||
#endif
|
||||
|
||||
BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN);
|
||||
cstate->resp_length = MS_CHAP_RESPONSE_LEN;
|
||||
}
|
||||
|
||||
#endif /* MSCHAP_SUPPORT */
|
||||
|
||||
#endif /* PPP_SUPPORT */
|
||||
|
||||
@@ -59,20 +59,14 @@
|
||||
|
||||
#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "ppp.h"
|
||||
#include "ppp_impl.h"
|
||||
#include "pppdebug.h"
|
||||
|
||||
#include "fsm.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/*************************/
|
||||
/*** LOCAL DEFINITIONS ***/
|
||||
/*************************/
|
||||
|
||||
#if PPP_DEBUG
|
||||
|
||||
static const char *ppperr_strerr[] = {
|
||||
"LS_INITIAL", /* LS_INITIAL 0 */
|
||||
"LS_STARTING", /* LS_STARTING 1 */
|
||||
@@ -85,17 +79,8 @@ static const char *ppperr_strerr[] = {
|
||||
"LS_ACKSENT", /* LS_ACKSENT 8 */
|
||||
"LS_OPENED" /* LS_OPENED 9 */
|
||||
};
|
||||
|
||||
#endif /* PPP_DEBUG */
|
||||
|
||||
/************************/
|
||||
/*** LOCAL DATA TYPES ***/
|
||||
/************************/
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** LOCAL FUNCTION DECLARATIONS ***/
|
||||
/***********************************/
|
||||
static void fsm_timeout (void *);
|
||||
static void fsm_rconfreq (fsm *, u_char, u_char *, int);
|
||||
static void fsm_rconfack (fsm *, int, u_char *, int);
|
||||
@@ -107,22 +92,9 @@ static void fsm_sconfreq (fsm *, int);
|
||||
|
||||
#define PROTO_NAME(f) ((f)->callbacks->proto_name)
|
||||
|
||||
|
||||
/******************************/
|
||||
/*** PUBLIC DATA STRUCTURES ***/
|
||||
/******************************/
|
||||
|
||||
|
||||
/*****************************/
|
||||
/*** LOCAL DATA STRUCTURES ***/
|
||||
/*****************************/
|
||||
int peer_mru[NUM_PPP];
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** PUBLIC FUNCTION DEFINITIONS ***/
|
||||
/***********************************/
|
||||
|
||||
/*
|
||||
* fsm_init - Initialize fsm.
|
||||
*
|
||||
@@ -168,11 +140,11 @@ fsm_lowerup(fsm *f)
|
||||
break;
|
||||
|
||||
default:
|
||||
FSMDEBUG((LOG_INFO, "%s: Up event in state %d (%s)!\n",
|
||||
FSMDEBUG(LOG_INFO, ("%s: Up event in state %d (%s)!\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
}
|
||||
|
||||
FSMDEBUG((LOG_INFO, "%s: lowerup state %d (%s) -> %d (%s)\n",
|
||||
|
||||
FSMDEBUG(LOG_INFO, ("%s: lowerup state %d (%s) -> %d (%s)\n",
|
||||
PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state]));
|
||||
}
|
||||
|
||||
@@ -222,11 +194,11 @@ fsm_lowerdown(fsm *f)
|
||||
break;
|
||||
|
||||
default:
|
||||
FSMDEBUG((LOG_INFO, "%s: Down event in state %d (%s)!\n",
|
||||
FSMDEBUG(LOG_INFO, ("%s: Down event in state %d (%s)!\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
}
|
||||
|
||||
FSMDEBUG((LOG_INFO, "%s: lowerdown state %d (%s) -> %d (%s)\n",
|
||||
FSMDEBUG(LOG_INFO, ("%s: lowerdown state %d (%s) -> %d (%s)\n",
|
||||
PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state]));
|
||||
}
|
||||
|
||||
@@ -271,10 +243,23 @@ fsm_open(fsm *f)
|
||||
break;
|
||||
}
|
||||
|
||||
FSMDEBUG((LOG_INFO, "%s: open state %d (%s) -> %d (%s)\n",
|
||||
FSMDEBUG(LOG_INFO, ("%s: open state %d (%s) -> %d (%s)\n",
|
||||
PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state]));
|
||||
}
|
||||
|
||||
#if 0 /* backport pppd 2.4.4b1; */
|
||||
/*
|
||||
* terminate_layer - Start process of shutting down the FSM
|
||||
*
|
||||
* Cancel any timeout running, notify upper layers we're done, and
|
||||
* send a terminate-request message as configured.
|
||||
*/
|
||||
static void
|
||||
terminate_layer(fsm *f, int nextstate)
|
||||
{
|
||||
/* @todo */
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* fsm_close - Start closing connection.
|
||||
@@ -290,7 +275,7 @@ fsm_close(fsm *f, char *reason)
|
||||
LWIP_UNUSED_ARG(oldState);
|
||||
|
||||
f->term_reason = reason;
|
||||
f->term_reason_len = (reason == NULL? 0: strlen(reason));
|
||||
f->term_reason_len = (reason == NULL ? 0 : (int)strlen(reason));
|
||||
switch( f->state ) {
|
||||
case LS_STARTING:
|
||||
f->state = LS_INITIAL;
|
||||
@@ -322,38 +307,71 @@ fsm_close(fsm *f, char *reason)
|
||||
break;
|
||||
}
|
||||
|
||||
FSMDEBUG((LOG_INFO, "%s: close reason=%s state %d (%s) -> %d (%s)\n",
|
||||
FSMDEBUG(LOG_INFO, ("%s: close reason=%s state %d (%s) -> %d (%s)\n",
|
||||
PROTO_NAME(f), reason, oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state]));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_sdata - Send some data.
|
||||
*
|
||||
* Used for all packets sent to our peer by this module.
|
||||
* fsm_timeout - Timeout expired.
|
||||
*/
|
||||
void
|
||||
fsm_sdata( fsm *f, u_char code, u_char id, u_char *data, int datalen)
|
||||
static void
|
||||
fsm_timeout(void *arg)
|
||||
{
|
||||
u_char *outp;
|
||||
int outlen;
|
||||
fsm *f = (fsm *) arg;
|
||||
|
||||
/* Adjust length to be smaller than MTU */
|
||||
outp = outpacket_buf[f->unit];
|
||||
if (datalen > peer_mru[f->unit] - (int)HEADERLEN) {
|
||||
datalen = peer_mru[f->unit] - HEADERLEN;
|
||||
switch (f->state) {
|
||||
case LS_CLOSING:
|
||||
case LS_STOPPING:
|
||||
if( f->retransmits <= 0 ) {
|
||||
FSMDEBUG(LOG_WARNING, ("%s: timeout sending Terminate-Request state=%d (%s)\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
/*
|
||||
* We've waited for an ack long enough. Peer probably heard us.
|
||||
*/
|
||||
f->state = (f->state == LS_CLOSING)? LS_CLOSED: LS_STOPPED;
|
||||
if( f->callbacks->finished ) {
|
||||
(*f->callbacks->finished)(f);
|
||||
}
|
||||
} else {
|
||||
FSMDEBUG(LOG_WARNING, ("%s: timeout resending Terminate-Requests state=%d (%s)\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
/* Send Terminate-Request */
|
||||
fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
|
||||
(u_char *) f->term_reason, f->term_reason_len);
|
||||
TIMEOUT(fsm_timeout, f, f->timeouttime);
|
||||
--f->retransmits;
|
||||
}
|
||||
break;
|
||||
|
||||
case LS_REQSENT:
|
||||
case LS_ACKRCVD:
|
||||
case LS_ACKSENT:
|
||||
if (f->retransmits <= 0) {
|
||||
FSMDEBUG(LOG_WARNING, ("%s: timeout sending Config-Requests state=%d (%s)\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
f->state = LS_STOPPED;
|
||||
if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) {
|
||||
(*f->callbacks->finished)(f);
|
||||
}
|
||||
} else {
|
||||
FSMDEBUG(LOG_WARNING, ("%s: timeout resending Config-Request state=%d (%s)\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
/* Retransmit the configure-request */
|
||||
if (f->callbacks->retransmit) {
|
||||
(*f->callbacks->retransmit)(f);
|
||||
}
|
||||
fsm_sconfreq(f, 1); /* Re-send Configure-Request */
|
||||
if( f->state == LS_ACKRCVD ) {
|
||||
f->state = LS_REQSENT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
FSMDEBUG(LOG_INFO, ("%s: UNHANDLED timeout event in state %d (%s)!\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
}
|
||||
if (datalen && data != outp + PPP_HDRLEN + HEADERLEN) {
|
||||
BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen);
|
||||
}
|
||||
outlen = datalen + HEADERLEN;
|
||||
MAKEHEADER(outp, f->protocol);
|
||||
PUTCHAR(code, outp);
|
||||
PUTCHAR(id, outp);
|
||||
PUTSHORT(outlen, outp);
|
||||
pppWrite(f->unit, outpacket_buf[f->unit], outlen + PPP_HDRLEN);
|
||||
FSMDEBUG((LOG_INFO, "fsm_sdata(%s): Sent code %d,%d,%d.\n",
|
||||
PROTO_NAME(f), code, id, outlen));
|
||||
}
|
||||
|
||||
|
||||
@@ -372,7 +390,7 @@ fsm_input(fsm *f, u_char *inpacket, int l)
|
||||
* If packet too short, drop it.
|
||||
*/
|
||||
if (l < HEADERLEN) {
|
||||
FSMDEBUG((LOG_WARNING, "fsm_input(%x): Rcvd short header.\n",
|
||||
FSMDEBUG(LOG_WARNING, ("fsm_input(%x): Rcvd short header.\n",
|
||||
f->protocol));
|
||||
return;
|
||||
}
|
||||
@@ -380,23 +398,23 @@ fsm_input(fsm *f, u_char *inpacket, int l)
|
||||
GETCHAR(id, inp);
|
||||
GETSHORT(len, inp);
|
||||
if (len < HEADERLEN) {
|
||||
FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd illegal length.\n",
|
||||
FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd illegal length.\n",
|
||||
f->protocol));
|
||||
return;
|
||||
}
|
||||
if (len > l) {
|
||||
FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd short packet.\n",
|
||||
FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd short packet.\n",
|
||||
f->protocol));
|
||||
return;
|
||||
}
|
||||
len -= HEADERLEN; /* subtract header length */
|
||||
|
||||
if( f->state == LS_INITIAL || f->state == LS_STARTING ) {
|
||||
FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd packet in state %d (%s).\n",
|
||||
FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd packet in state %d (%s).\n",
|
||||
f->protocol, f->state, ppperr_strerr[f->state]));
|
||||
return;
|
||||
}
|
||||
FSMDEBUG((LOG_INFO, "fsm_input(%s):%d,%d,%d\n", PROTO_NAME(f), code, id, l));
|
||||
FSMDEBUG(LOG_INFO, ("fsm_input(%s):%d,%d,%d\n", PROTO_NAME(f), code, id, l));
|
||||
/*
|
||||
* Action depends on code.
|
||||
*/
|
||||
@@ -427,6 +445,7 @@ fsm_input(fsm *f, u_char *inpacket, int l)
|
||||
break;
|
||||
|
||||
default:
|
||||
FSMDEBUG(LOG_INFO, ("fsm_input(%s): default: \n", PROTO_NAME(f)));
|
||||
if( !f->callbacks->extcode ||
|
||||
!(*f->callbacks->extcode)(f, code, id, inp, len) ) {
|
||||
fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN);
|
||||
@@ -436,129 +455,6 @@ fsm_input(fsm *f, u_char *inpacket, int l)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_protreject - Peer doesn't speak this protocol.
|
||||
*
|
||||
* Treat this as a catastrophic error (RXJ-).
|
||||
*/
|
||||
void
|
||||
fsm_protreject(fsm *f)
|
||||
{
|
||||
switch( f->state ) {
|
||||
case LS_CLOSING:
|
||||
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||
/* fall through */
|
||||
case LS_CLOSED:
|
||||
f->state = LS_CLOSED;
|
||||
if( f->callbacks->finished ) {
|
||||
(*f->callbacks->finished)(f);
|
||||
}
|
||||
break;
|
||||
|
||||
case LS_STOPPING:
|
||||
case LS_REQSENT:
|
||||
case LS_ACKRCVD:
|
||||
case LS_ACKSENT:
|
||||
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||
/* fall through */
|
||||
case LS_STOPPED:
|
||||
f->state = LS_STOPPED;
|
||||
if( f->callbacks->finished ) {
|
||||
(*f->callbacks->finished)(f);
|
||||
}
|
||||
break;
|
||||
|
||||
case LS_OPENED:
|
||||
if( f->callbacks->down ) {
|
||||
(*f->callbacks->down)(f);
|
||||
}
|
||||
/* Init restart counter, send Terminate-Request */
|
||||
f->retransmits = f->maxtermtransmits;
|
||||
fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
|
||||
(u_char *) f->term_reason, f->term_reason_len);
|
||||
TIMEOUT(fsm_timeout, f, f->timeouttime);
|
||||
--f->retransmits;
|
||||
|
||||
f->state = LS_STOPPING;
|
||||
break;
|
||||
|
||||
default:
|
||||
FSMDEBUG((LOG_INFO, "%s: Protocol-reject event in state %d (%s)!\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**********************************/
|
||||
/*** LOCAL FUNCTION DEFINITIONS ***/
|
||||
/**********************************/
|
||||
|
||||
/*
|
||||
* fsm_timeout - Timeout expired.
|
||||
*/
|
||||
static void
|
||||
fsm_timeout(void *arg)
|
||||
{
|
||||
fsm *f = (fsm *) arg;
|
||||
|
||||
switch (f->state) {
|
||||
case LS_CLOSING:
|
||||
case LS_STOPPING:
|
||||
if( f->retransmits <= 0 ) {
|
||||
FSMDEBUG((LOG_WARNING, "%s: timeout sending Terminate-Request state=%d (%s)\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
/*
|
||||
* We've waited for an ack long enough. Peer probably heard us.
|
||||
*/
|
||||
f->state = (f->state == LS_CLOSING)? LS_CLOSED: LS_STOPPED;
|
||||
if( f->callbacks->finished ) {
|
||||
(*f->callbacks->finished)(f);
|
||||
}
|
||||
} else {
|
||||
FSMDEBUG((LOG_WARNING, "%s: timeout resending Terminate-Requests state=%d (%s)\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
/* Send Terminate-Request */
|
||||
fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
|
||||
(u_char *) f->term_reason, f->term_reason_len);
|
||||
TIMEOUT(fsm_timeout, f, f->timeouttime);
|
||||
--f->retransmits;
|
||||
}
|
||||
break;
|
||||
|
||||
case LS_REQSENT:
|
||||
case LS_ACKRCVD:
|
||||
case LS_ACKSENT:
|
||||
if (f->retransmits <= 0) {
|
||||
FSMDEBUG((LOG_WARNING, "%s: timeout sending Config-Requests state=%d (%s)\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
f->state = LS_STOPPED;
|
||||
if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) {
|
||||
(*f->callbacks->finished)(f);
|
||||
}
|
||||
} else {
|
||||
FSMDEBUG((LOG_WARNING, "%s: timeout resending Config-Request state=%d (%s)\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
/* Retransmit the configure-request */
|
||||
if (f->callbacks->retransmit) {
|
||||
(*f->callbacks->retransmit)(f);
|
||||
}
|
||||
fsm_sconfreq(f, 1); /* Re-send Configure-Request */
|
||||
if( f->state == LS_ACKRCVD ) {
|
||||
f->state = LS_REQSENT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
FSMDEBUG((LOG_INFO, "%s: UNHANDLED timeout event in state %d (%s)!\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_rconfreq - Receive Configure-Request.
|
||||
*/
|
||||
@@ -567,7 +463,7 @@ fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len)
|
||||
{
|
||||
int code, reject_if_disagree;
|
||||
|
||||
FSMDEBUG((LOG_INFO, "fsm_rconfreq(%s): Rcvd id %d state=%d (%s)\n",
|
||||
FSMDEBUG(LOG_INFO, ("fsm_rconfreq(%s): Rcvd id %d state=%d (%s)\n",
|
||||
PROTO_NAME(f), id, f->state, ppperr_strerr[f->state]));
|
||||
switch( f->state ) {
|
||||
case LS_CLOSED:
|
||||
@@ -638,7 +534,7 @@ fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len)
|
||||
static void
|
||||
fsm_rconfack(fsm *f, int id, u_char *inp, int len)
|
||||
{
|
||||
FSMDEBUG((LOG_INFO, "fsm_rconfack(%s): Rcvd id %d state=%d (%s)\n",
|
||||
FSMDEBUG(LOG_INFO, ("fsm_rconfack(%s): Rcvd id %d state=%d (%s)\n",
|
||||
PROTO_NAME(f), id, f->state, ppperr_strerr[f->state]));
|
||||
|
||||
if (id != f->reqid || f->seen_ack) { /* Expected id? */
|
||||
@@ -646,7 +542,7 @@ fsm_rconfack(fsm *f, int id, u_char *inp, int len)
|
||||
}
|
||||
if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): (len == 0)) ) {
|
||||
/* Ack is bad - ignore it */
|
||||
FSMDEBUG((LOG_INFO, "%s: received bad Ack (length %d)\n",
|
||||
FSMDEBUG(LOG_INFO, ("%s: received bad Ack (length %d)\n",
|
||||
PROTO_NAME(f), len));
|
||||
return;
|
||||
}
|
||||
@@ -700,7 +596,7 @@ fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len)
|
||||
int (*proc) (fsm *, u_char *, int);
|
||||
int ret;
|
||||
|
||||
FSMDEBUG((LOG_INFO, "fsm_rconfnakrej(%s): Rcvd id %d state=%d (%s)\n",
|
||||
FSMDEBUG(LOG_INFO, ("fsm_rconfnakrej(%s): Rcvd id %d state=%d (%s)\n",
|
||||
PROTO_NAME(f), id, f->state, ppperr_strerr[f->state]));
|
||||
|
||||
if (id != f->reqid || f->seen_ack) { /* Expected id? */
|
||||
@@ -709,7 +605,7 @@ fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len)
|
||||
proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci;
|
||||
if (!proc || !((ret = proc(f, inp, len)))) {
|
||||
/* Nak/reject is bad - ignore it */
|
||||
FSMDEBUG((LOG_INFO, "%s: received bad %s (length %d)\n",
|
||||
FSMDEBUG(LOG_INFO, ("%s: received bad %s (length %d)\n",
|
||||
PROTO_NAME(f), (code==CONFNAK? "Nak": "reject"), len));
|
||||
return;
|
||||
}
|
||||
@@ -759,7 +655,7 @@ fsm_rtermreq(fsm *f, int id, u_char *p, int len)
|
||||
{
|
||||
LWIP_UNUSED_ARG(p);
|
||||
|
||||
FSMDEBUG((LOG_INFO, "fsm_rtermreq(%s): Rcvd id %d state=%d (%s)\n",
|
||||
FSMDEBUG(LOG_INFO, ("fsm_rtermreq(%s): Rcvd id %d state=%d (%s)\n",
|
||||
PROTO_NAME(f), id, f->state, ppperr_strerr[f->state]));
|
||||
|
||||
switch (f->state) {
|
||||
@@ -770,9 +666,9 @@ fsm_rtermreq(fsm *f, int id, u_char *p, int len)
|
||||
|
||||
case LS_OPENED:
|
||||
if (len > 0) {
|
||||
FSMDEBUG((LOG_INFO, "%s terminated by peer (%x)\n", PROTO_NAME(f), p));
|
||||
FSMDEBUG(LOG_INFO, ("%s terminated by peer (%p)\n", PROTO_NAME(f), p));
|
||||
} else {
|
||||
FSMDEBUG((LOG_INFO, "%s terminated by peer\n", PROTO_NAME(f)));
|
||||
FSMDEBUG(LOG_INFO, ("%s terminated by peer\n", PROTO_NAME(f)));
|
||||
}
|
||||
if (f->callbacks->down) {
|
||||
(*f->callbacks->down)(f); /* Inform upper layers */
|
||||
@@ -793,7 +689,7 @@ fsm_rtermreq(fsm *f, int id, u_char *p, int len)
|
||||
static void
|
||||
fsm_rtermack(fsm *f)
|
||||
{
|
||||
FSMDEBUG((LOG_INFO, "fsm_rtermack(%s): state=%d (%s)\n",
|
||||
FSMDEBUG(LOG_INFO, ("fsm_rtermack(%s): state=%d (%s)\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
|
||||
switch (f->state) {
|
||||
@@ -823,6 +719,9 @@ fsm_rtermack(fsm *f)
|
||||
}
|
||||
fsm_sconfreq(f, 0);
|
||||
break;
|
||||
default:
|
||||
FSMDEBUG(LOG_INFO, ("fsm_rtermack(%s): UNHANDLED state=%d (%s)!!!\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -835,16 +734,16 @@ fsm_rcoderej(fsm *f, u_char *inp, int len)
|
||||
{
|
||||
u_char code, id;
|
||||
|
||||
FSMDEBUG((LOG_INFO, "fsm_rcoderej(%s): state=%d (%s)\n",
|
||||
FSMDEBUG(LOG_INFO, ("fsm_rcoderej(%s): state=%d (%s)\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
|
||||
if (len < HEADERLEN) {
|
||||
FSMDEBUG((LOG_INFO, "fsm_rcoderej: Rcvd short Code-Reject packet!\n"));
|
||||
FSMDEBUG(LOG_INFO, ("fsm_rcoderej: Rcvd short Code-Reject packet!\n"));
|
||||
return;
|
||||
}
|
||||
GETCHAR(code, inp);
|
||||
GETCHAR(id, inp);
|
||||
FSMDEBUG((LOG_WARNING, "%s: Rcvd Code-Reject for code %d, id %d\n",
|
||||
FSMDEBUG(LOG_WARNING, ("%s: Rcvd Code-Reject for code %d, id %d\n",
|
||||
PROTO_NAME(f), code, id));
|
||||
|
||||
if( f->state == LS_ACKRCVD ) {
|
||||
@@ -853,6 +752,59 @@ fsm_rcoderej(fsm *f, u_char *inp, int len)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_protreject - Peer doesn't speak this protocol.
|
||||
*
|
||||
* Treat this as a catastrophic error (RXJ-).
|
||||
*/
|
||||
void
|
||||
fsm_protreject(fsm *f)
|
||||
{
|
||||
switch( f->state ) {
|
||||
case LS_CLOSING:
|
||||
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||
/* fall through */
|
||||
case LS_CLOSED:
|
||||
f->state = LS_CLOSED;
|
||||
if( f->callbacks->finished ) {
|
||||
(*f->callbacks->finished)(f);
|
||||
}
|
||||
break;
|
||||
|
||||
case LS_STOPPING:
|
||||
case LS_REQSENT:
|
||||
case LS_ACKRCVD:
|
||||
case LS_ACKSENT:
|
||||
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||
/* fall through */
|
||||
case LS_STOPPED:
|
||||
f->state = LS_STOPPED;
|
||||
if( f->callbacks->finished ) {
|
||||
(*f->callbacks->finished)(f);
|
||||
}
|
||||
break;
|
||||
|
||||
case LS_OPENED:
|
||||
if( f->callbacks->down ) {
|
||||
(*f->callbacks->down)(f);
|
||||
}
|
||||
/* Init restart counter, send Terminate-Request */
|
||||
f->retransmits = f->maxtermtransmits;
|
||||
fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
|
||||
(u_char *) f->term_reason, f->term_reason_len);
|
||||
TIMEOUT(fsm_timeout, f, f->timeouttime);
|
||||
--f->retransmits;
|
||||
|
||||
f->state = LS_STOPPING;
|
||||
break;
|
||||
|
||||
default:
|
||||
FSMDEBUG(LOG_INFO, ("%s: Protocol-reject event in state %d (%s)!\n",
|
||||
PROTO_NAME(f), f->state, ppperr_strerr[f->state]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_sconfreq - Send a Configure-Request.
|
||||
*/
|
||||
@@ -901,8 +853,38 @@ fsm_sconfreq(fsm *f, int retransmit)
|
||||
--f->retransmits;
|
||||
TIMEOUT(fsm_timeout, f, f->timeouttime);
|
||||
|
||||
FSMDEBUG((LOG_INFO, "%s: sending Configure-Request, id %d\n",
|
||||
FSMDEBUG(LOG_INFO, ("%s: sending Configure-Request, id %d\n",
|
||||
PROTO_NAME(f), f->reqid));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_sdata - Send some data.
|
||||
*
|
||||
* Used for all packets sent to our peer by this module.
|
||||
*/
|
||||
void
|
||||
fsm_sdata( fsm *f, u_char code, u_char id, u_char *data, int datalen)
|
||||
{
|
||||
u_char *outp;
|
||||
int outlen;
|
||||
|
||||
/* Adjust length to be smaller than MTU */
|
||||
outp = outpacket_buf[f->unit];
|
||||
if (datalen > peer_mru[f->unit] - (int)HEADERLEN) {
|
||||
datalen = peer_mru[f->unit] - HEADERLEN;
|
||||
}
|
||||
if (datalen && data != outp + PPP_HDRLEN + HEADERLEN) {
|
||||
BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen);
|
||||
}
|
||||
outlen = datalen + HEADERLEN;
|
||||
MAKEHEADER(outp, f->protocol);
|
||||
PUTCHAR(code, outp);
|
||||
PUTCHAR(id, outp);
|
||||
PUTSHORT(outlen, outp);
|
||||
pppWrite(f->unit, outpacket_buf[f->unit], outlen + PPP_HDRLEN);
|
||||
FSMDEBUG(LOG_INFO, ("fsm_sdata(%s): Sent code %d,%d,%d.\n",
|
||||
PROTO_NAME(f), code, id, outlen));
|
||||
}
|
||||
|
||||
#endif /* PPP_SUPPORT */
|
||||
|
||||
@@ -48,15 +48,12 @@
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id: fsm.h,v 1.4 2007/12/19 20:47:23 fbernon Exp $
|
||||
* $Id: fsm.h,v 1.5 2009/12/31 17:08:08 goldsimon Exp $
|
||||
*/
|
||||
|
||||
#ifndef FSM_H
|
||||
#define FSM_H
|
||||
|
||||
/*****************************************************************************
|
||||
************************* PUBLIC DEFINITIONS *********************************
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* LCP Packet header = Code, id, length.
|
||||
*/
|
||||
@@ -74,31 +71,7 @@
|
||||
#define TERMACK 6 /* Termination Ack */
|
||||
#define CODEREJ 7 /* Code Reject */
|
||||
|
||||
/*
|
||||
* Link states.
|
||||
*/
|
||||
#define LS_INITIAL 0 /* Down, hasn't been opened */
|
||||
#define LS_STARTING 1 /* Down, been opened */
|
||||
#define LS_CLOSED 2 /* Up, hasn't been opened */
|
||||
#define LS_STOPPED 3 /* Open, waiting for down event */
|
||||
#define LS_CLOSING 4 /* Terminating the connection, not open */
|
||||
#define LS_STOPPING 5 /* Terminating, but open */
|
||||
#define LS_REQSENT 6 /* We've sent a Config Request */
|
||||
#define LS_ACKRCVD 7 /* We've received a Config Ack */
|
||||
#define LS_ACKSENT 8 /* We've sent a Config Ack */
|
||||
#define LS_OPENED 9 /* Connection available */
|
||||
|
||||
/*
|
||||
* Flags - indicate options controlling FSM operation
|
||||
*/
|
||||
#define OPT_PASSIVE 1 /* Don't die if we don't get a response */
|
||||
#define OPT_RESTART 2 /* Treat 2nd OPEN as DOWN, UP */
|
||||
#define OPT_SILENT 4 /* Wait for peer to speak first */
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
************************* PUBLIC DATA TYPES **********************************
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* Each FSM is described by an fsm structure and fsm callbacks.
|
||||
*/
|
||||
@@ -141,18 +114,27 @@ typedef struct fsm_callbacks {
|
||||
} fsm_callbacks;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*********************** PUBLIC DATA STRUCTURES *******************************
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* Variables
|
||||
* Link states.
|
||||
*/
|
||||
extern int peer_mru[]; /* currently negotiated peer MRU (per unit) */
|
||||
#define LS_INITIAL 0 /* Down, hasn't been opened */
|
||||
#define LS_STARTING 1 /* Down, been opened */
|
||||
#define LS_CLOSED 2 /* Up, hasn't been opened */
|
||||
#define LS_STOPPED 3 /* Open, waiting for down event */
|
||||
#define LS_CLOSING 4 /* Terminating the connection, not open */
|
||||
#define LS_STOPPING 5 /* Terminating, but open */
|
||||
#define LS_REQSENT 6 /* We've sent a Config Request */
|
||||
#define LS_ACKRCVD 7 /* We've received a Config Ack */
|
||||
#define LS_ACKSENT 8 /* We've sent a Config Ack */
|
||||
#define LS_OPENED 9 /* Connection available */
|
||||
|
||||
/*
|
||||
* Flags - indicate options controlling FSM operation
|
||||
*/
|
||||
#define OPT_PASSIVE 1 /* Don't die if we don't get a response */
|
||||
#define OPT_RESTART 2 /* Treat 2nd OPEN as DOWN, UP */
|
||||
#define OPT_SILENT 4 /* Wait for peer to speak first */
|
||||
|
||||
/*****************************************************************************
|
||||
************************** PUBLIC FUNCTIONS **********************************
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Prototypes
|
||||
@@ -166,4 +148,10 @@ void fsm_input (fsm*, u_char*, int);
|
||||
void fsm_protreject (fsm*);
|
||||
void fsm_sdata (fsm*, u_char, u_char, u_char*, int);
|
||||
|
||||
|
||||
/*
|
||||
* Variables
|
||||
*/
|
||||
extern int peer_mru[]; /* currently negotiated peer MRU (per unit) */
|
||||
|
||||
#endif /* FSM_H */
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/** In contrast to pppd 2.3.1, DNS support has been added, proxy-ARP and
|
||||
dial-on-demand has been stripped. */
|
||||
/*****************************************************************************
|
||||
* ipcp.c - Network PPP IP Control Protocol program file.
|
||||
*
|
||||
@@ -53,7 +55,7 @@
|
||||
|
||||
#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "ppp.h"
|
||||
#include "ppp_impl.h"
|
||||
#include "pppdebug.h"
|
||||
|
||||
#include "auth.h"
|
||||
@@ -61,27 +63,23 @@
|
||||
#include "vj.h"
|
||||
#include "ipcp.h"
|
||||
|
||||
#include "lwip/inet.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/*************************/
|
||||
/*** LOCAL DEFINITIONS ***/
|
||||
/*************************/
|
||||
/* #define OLD_CI_ADDRS 1 */ /* Support deprecated address negotiation. */
|
||||
|
||||
/*
|
||||
* Lengths of configuration options.
|
||||
*/
|
||||
#define CILEN_VOID 2
|
||||
#define CILEN_COMPRESS 4 /* min length for compression protocol opt. */
|
||||
#define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */
|
||||
#define CILEN_ADDR 6 /* new-style single address option */
|
||||
#define CILEN_ADDRS 10 /* old-style dual address option */
|
||||
/* global vars */
|
||||
ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */
|
||||
ipcp_options ipcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
|
||||
ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
|
||||
ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
|
||||
|
||||
/* local vars */
|
||||
static int default_route_set[NUM_PPP]; /* Have set up a default route */
|
||||
static int cis_received[NUM_PPP]; /* # Conf-Reqs received */
|
||||
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** LOCAL FUNCTION DECLARATIONS ***/
|
||||
/***********************************/
|
||||
/*
|
||||
* Callbacks for fsm code. (CI = Configuration Information)
|
||||
*/
|
||||
@@ -94,70 +92,14 @@ static int ipcp_rejci (fsm *, u_char *, int); /* Peer rej'd our CI */
|
||||
static int ipcp_reqci (fsm *, u_char *, int *, int); /* Rcv CI */
|
||||
static void ipcp_up (fsm *); /* We're UP */
|
||||
static void ipcp_down (fsm *); /* We're DOWN */
|
||||
#if 0
|
||||
#if PPP_ADDITIONAL_CALLBACKS
|
||||
static void ipcp_script (fsm *, char *); /* Run an up/down script */
|
||||
#endif
|
||||
static void ipcp_finished (fsm *); /* Don't need lower layer */
|
||||
|
||||
/*
|
||||
* Protocol entry points from main code.
|
||||
*/
|
||||
static void ipcp_init (int);
|
||||
static void ipcp_open (int);
|
||||
static void ipcp_close (int, char *);
|
||||
static void ipcp_lowerup (int);
|
||||
static void ipcp_lowerdown (int);
|
||||
static void ipcp_input (int, u_char *, int);
|
||||
static void ipcp_protrej (int);
|
||||
|
||||
static void ipcp_clear_addrs (int);
|
||||
|
||||
#define CODENAME(x) ((x) == CONFACK ? "ACK" : \
|
||||
(x) == CONFNAK ? "NAK" : "REJ")
|
||||
|
||||
|
||||
|
||||
/******************************/
|
||||
/*** PUBLIC DATA STRUCTURES ***/
|
||||
/******************************/
|
||||
/* global vars */
|
||||
ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */
|
||||
ipcp_options ipcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
|
||||
ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
|
||||
ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
|
||||
|
||||
fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */
|
||||
|
||||
struct protent ipcp_protent = {
|
||||
PPP_IPCP,
|
||||
ipcp_init,
|
||||
ipcp_input,
|
||||
ipcp_protrej,
|
||||
ipcp_lowerup,
|
||||
ipcp_lowerdown,
|
||||
ipcp_open,
|
||||
ipcp_close,
|
||||
#if 0
|
||||
ipcp_printpkt,
|
||||
NULL,
|
||||
#endif
|
||||
1,
|
||||
"IPCP",
|
||||
#if 0
|
||||
ip_check_options,
|
||||
NULL,
|
||||
ip_active_pkt
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*****************************/
|
||||
/*** LOCAL DATA STRUCTURES ***/
|
||||
/*****************************/
|
||||
/* local vars */
|
||||
static int cis_received[NUM_PPP]; /* # Conf-Reqs received */
|
||||
static int default_route_set[NUM_PPP]; /* Have set up a default route */
|
||||
|
||||
static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
|
||||
ipcp_resetci, /* Reset our Configuration Information */
|
||||
@@ -177,13 +119,55 @@ static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
|
||||
"IPCP" /* String name of protocol */
|
||||
};
|
||||
|
||||
/*
|
||||
* Protocol entry points from main code.
|
||||
*/
|
||||
static void ipcp_init (int);
|
||||
static void ipcp_open (int);
|
||||
static void ipcp_close (int, char *);
|
||||
static void ipcp_lowerup (int);
|
||||
static void ipcp_lowerdown (int);
|
||||
static void ipcp_input (int, u_char *, int);
|
||||
static void ipcp_protrej (int);
|
||||
|
||||
|
||||
/**********************************/
|
||||
/*** LOCAL FUNCTION DEFINITIONS ***/
|
||||
/**********************************/
|
||||
struct protent ipcp_protent = {
|
||||
PPP_IPCP,
|
||||
ipcp_init,
|
||||
ipcp_input,
|
||||
ipcp_protrej,
|
||||
ipcp_lowerup,
|
||||
ipcp_lowerdown,
|
||||
ipcp_open,
|
||||
ipcp_close,
|
||||
#if PPP_ADDITIONAL_CALLBACKS
|
||||
ipcp_printpkt,
|
||||
NULL,
|
||||
#endif /* PPP_ADDITIONAL_CALLBACKS */
|
||||
1,
|
||||
"IPCP",
|
||||
#if PPP_ADDITIONAL_CALLBACKS
|
||||
ip_check_options,
|
||||
NULL,
|
||||
ip_active_pkt
|
||||
#endif /* PPP_ADDITIONAL_CALLBACKS */
|
||||
};
|
||||
|
||||
static void ipcp_clear_addrs (int);
|
||||
|
||||
/*
|
||||
* Lengths of configuration options.
|
||||
*/
|
||||
#define CILEN_VOID 2
|
||||
#define CILEN_COMPRESS 4 /* min length for compression protocol opt. */
|
||||
#define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */
|
||||
#define CILEN_ADDR 6 /* new-style single address option */
|
||||
#define CILEN_ADDRS 10 /* old-style dual address option */
|
||||
|
||||
|
||||
#define CODENAME(x) ((x) == CONFACK ? "ACK" : \
|
||||
(x) == CONFNAK ? "NAK" : "REJ")
|
||||
|
||||
#define inet_ntoa(addr) ip_ntoa(((struct ip_addr*)&(addr)))
|
||||
|
||||
/*
|
||||
* ipcp_init - Initialize IPCP.
|
||||
@@ -542,9 +526,9 @@ ipcp_ackci(fsm *f, u_char *p, int len)
|
||||
goto bad;
|
||||
}
|
||||
return (1);
|
||||
|
||||
|
||||
bad:
|
||||
IPCPDEBUG((LOG_INFO, "ipcp_ackci: received bad Ack!\n"));
|
||||
IPCPDEBUG(LOG_INFO, ("ipcp_ackci: received bad Ack!\n"));
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -628,12 +612,12 @@ ipcp_nakci(fsm *f, u_char *p, int len)
|
||||
NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs,
|
||||
if (go->accept_local && ciaddr1) { /* Do we know our address? */
|
||||
try.ouraddr = ciaddr1;
|
||||
IPCPDEBUG((LOG_INFO, "local IP address %s\n",
|
||||
IPCPDEBUG(LOG_INFO, ("local IP address %s\n",
|
||||
inet_ntoa(ciaddr1)));
|
||||
}
|
||||
if (go->accept_remote && ciaddr2) { /* Does he know his? */
|
||||
try.hisaddr = ciaddr2;
|
||||
IPCPDEBUG((LOG_INFO, "remote IP address %s\n",
|
||||
IPCPDEBUG(LOG_INFO, ("remote IP address %s\n",
|
||||
inet_ntoa(ciaddr2)));
|
||||
}
|
||||
);
|
||||
@@ -671,12 +655,12 @@ ipcp_nakci(fsm *f, u_char *p, int len)
|
||||
|
||||
NAKCIDNS(CI_MS_DNS1, req_dns1,
|
||||
try.dnsaddr[0] = cidnsaddr;
|
||||
IPCPDEBUG((LOG_INFO, "primary DNS address %s\n", inet_ntoa(cidnsaddr)));
|
||||
IPCPDEBUG(LOG_INFO, ("primary DNS address %s\n", inet_ntoa(cidnsaddr)));
|
||||
);
|
||||
|
||||
NAKCIDNS(CI_MS_DNS2, req_dns2,
|
||||
try.dnsaddr[1] = cidnsaddr;
|
||||
IPCPDEBUG((LOG_INFO, "secondary DNS address %s\n", inet_ntoa(cidnsaddr)));
|
||||
IPCPDEBUG(LOG_INFO, ("secondary DNS address %s\n", inet_ntoa(cidnsaddr)));
|
||||
);
|
||||
|
||||
/*
|
||||
@@ -754,7 +738,7 @@ ipcp_nakci(fsm *f, u_char *p, int len)
|
||||
return 1;
|
||||
|
||||
bad:
|
||||
IPCPDEBUG((LOG_INFO, "ipcp_nakci: received bad Nak!\n"));
|
||||
IPCPDEBUG(LOG_INFO, ("ipcp_nakci: received bad Nak!\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -869,7 +853,7 @@ ipcp_rejci(fsm *f, u_char *p, int len)
|
||||
return 1;
|
||||
|
||||
bad:
|
||||
IPCPDEBUG((LOG_INFO, "ipcp_rejci: received bad Reject!\n"));
|
||||
IPCPDEBUG(LOG_INFO, ("ipcp_rejci: received bad Reject!\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -922,9 +906,9 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
|
||||
if (l < 2 || /* Not enough data for CI header or */
|
||||
p[1] < 2 || /* CI length too small or */
|
||||
p[1] > l) { /* CI length too big? */
|
||||
IPCPDEBUG((LOG_INFO, "ipcp_reqci: bad CI length!\n"));
|
||||
IPCPDEBUG(LOG_INFO, ("ipcp_reqci: bad CI length!\n"));
|
||||
orc = CONFREJ; /* Reject bad CI */
|
||||
cilen = l; /* Reject till end of packet */
|
||||
cilen = (u_short)l;/* Reject till end of packet */
|
||||
l = 0; /* Don't loop again */
|
||||
goto endswitch;
|
||||
}
|
||||
@@ -936,7 +920,7 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
|
||||
switch (citype) { /* Check CI type */
|
||||
#ifdef OLD_CI_ADDRS /* Need to save space... */
|
||||
case CI_ADDRS:
|
||||
IPCPDEBUG((LOG_INFO, "ipcp_reqci: received ADDRS\n"));
|
||||
IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received ADDRS\n"));
|
||||
if (!ao->neg_addr ||
|
||||
cilen != CILEN_ADDRS) { /* Check CI length */
|
||||
orc = CONFREJ; /* Reject CI */
|
||||
@@ -951,7 +935,7 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
|
||||
*/
|
||||
GETLONG(tl, p); /* Parse source address (his) */
|
||||
ciaddr1 = htonl(tl);
|
||||
IPCPDEBUG((LOG_INFO, "his addr %s\n", inet_ntoa(ciaddr1)));
|
||||
IPCPDEBUG(LOG_INFO, ("his addr %s\n", inet_ntoa(ciaddr1)));
|
||||
if (ciaddr1 != wo->hisaddr
|
||||
&& (ciaddr1 == 0 || !wo->accept_remote)) {
|
||||
orc = CONFNAK;
|
||||
@@ -975,7 +959,7 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
|
||||
*/
|
||||
GETLONG(tl, p); /* Parse desination address (ours) */
|
||||
ciaddr2 = htonl(tl);
|
||||
IPCPDEBUG((LOG_INFO, "our addr %s\n", inet_ntoa(ciaddr2)));
|
||||
IPCPDEBUG(LOG_INFO, ("our addr %s\n", inet_ntoa(ciaddr2)));
|
||||
if (ciaddr2 != wo->ouraddr) {
|
||||
if (ciaddr2 == 0 || !wo->accept_local) {
|
||||
orc = CONFNAK;
|
||||
@@ -998,11 +982,11 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
|
||||
|
||||
case CI_ADDR:
|
||||
if (!ao->neg_addr) {
|
||||
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR not allowed\n"));
|
||||
IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR not allowed\n"));
|
||||
orc = CONFREJ; /* Reject CI */
|
||||
break;
|
||||
} else if (cilen != CILEN_ADDR) { /* Check CI length */
|
||||
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR bad len\n"));
|
||||
IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR bad len\n"));
|
||||
orc = CONFREJ; /* Reject CI */
|
||||
break;
|
||||
}
|
||||
@@ -1023,12 +1007,12 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
|
||||
tl = ntohl(wo->hisaddr);
|
||||
PUTLONG(tl, p);
|
||||
}
|
||||
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Nak ADDR %s\n", inet_ntoa(ciaddr1)));
|
||||
IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Nak ADDR %s\n", inet_ntoa(ciaddr1)));
|
||||
} else if (ciaddr1 == 0 && wo->hisaddr == 0) {
|
||||
/*
|
||||
* Don't ACK an address of 0.0.0.0 - reject it instead.
|
||||
*/
|
||||
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR %s\n", inet_ntoa(ciaddr1)));
|
||||
IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR %s\n", inet_ntoa(ciaddr1)));
|
||||
orc = CONFREJ;
|
||||
wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */
|
||||
break;
|
||||
@@ -1036,7 +1020,7 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
|
||||
|
||||
ho->neg_addr = 1;
|
||||
ho->hisaddr = ciaddr1;
|
||||
IPCPDEBUG((LOG_INFO, "ipcp_reqci: ADDR %s\n", inet_ntoa(ciaddr1)));
|
||||
IPCPDEBUG(LOG_INFO, ("ipcp_reqci: ADDR %s\n", inet_ntoa(ciaddr1)));
|
||||
break;
|
||||
|
||||
case CI_MS_DNS1:
|
||||
@@ -1047,27 +1031,27 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
|
||||
/* If we do not have a DNS address then we cannot send it */
|
||||
if (ao->dnsaddr[d] == 0 ||
|
||||
cilen != CILEN_ADDR) { /* Check CI length */
|
||||
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting DNS%d Request\n", d+1));
|
||||
IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting DNS%d Request\n", d+1));
|
||||
orc = CONFREJ; /* Reject CI */
|
||||
break;
|
||||
}
|
||||
GETLONG(tl, p);
|
||||
if (htonl(tl) != ao->dnsaddr[d]) {
|
||||
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking DNS%d Request %d\n",
|
||||
IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking DNS%d Request %s\n",
|
||||
d+1, inet_ntoa(tl)));
|
||||
DECPTR(sizeof(u32_t), p);
|
||||
tl = ntohl(ao->dnsaddr[d]);
|
||||
PUTLONG(tl, p);
|
||||
orc = CONFNAK;
|
||||
}
|
||||
IPCPDEBUG((LOG_INFO, "ipcp_reqci: received DNS%d Request\n", d+1));
|
||||
IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received DNS%d Request\n", d+1));
|
||||
break;
|
||||
|
||||
case CI_MS_WINS1:
|
||||
case CI_MS_WINS2:
|
||||
/* Microsoft primary or secondary WINS request */
|
||||
d = citype == CI_MS_WINS2;
|
||||
IPCPDEBUG((LOG_INFO, "ipcp_reqci: received WINS%d Request\n", d+1));
|
||||
IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received WINS%d Request\n", d+1));
|
||||
|
||||
/* If we do not have a DNS address then we cannot send it */
|
||||
if (ao->winsaddr[d] == 0 ||
|
||||
@@ -1086,11 +1070,11 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
|
||||
|
||||
case CI_COMPRESSTYPE:
|
||||
if (!ao->neg_vj) {
|
||||
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE not allowed\n"));
|
||||
IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE not allowed\n"));
|
||||
orc = CONFREJ;
|
||||
break;
|
||||
} else if (cilen != CILEN_VJ && cilen != CILEN_COMPRESS) {
|
||||
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE len=%d\n", cilen));
|
||||
IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE len=%d\n", cilen));
|
||||
orc = CONFREJ;
|
||||
break;
|
||||
}
|
||||
@@ -1098,7 +1082,7 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
|
||||
|
||||
if (!(cishort == IPCP_VJ_COMP ||
|
||||
(cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) {
|
||||
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE %d\n", cishort));
|
||||
IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE %d\n", cishort));
|
||||
orc = CONFREJ;
|
||||
break;
|
||||
}
|
||||
@@ -1108,7 +1092,7 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
|
||||
if (cilen == CILEN_VJ) {
|
||||
GETCHAR(maxslotindex, p);
|
||||
if (maxslotindex > ao->maxslotindex) {
|
||||
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking VJ max slot %d\n", maxslotindex));
|
||||
IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking VJ max slot %d\n", maxslotindex));
|
||||
orc = CONFNAK;
|
||||
if (!reject_if_disagree) {
|
||||
DECPTR(1, p);
|
||||
@@ -1117,7 +1101,7 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
|
||||
}
|
||||
GETCHAR(cflag, p);
|
||||
if (cflag && !ao->cflag) {
|
||||
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking VJ cflag %d\n", cflag));
|
||||
IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking VJ cflag %d\n", cflag));
|
||||
orc = CONFNAK;
|
||||
if (!reject_if_disagree) {
|
||||
DECPTR(1, p);
|
||||
@@ -1131,13 +1115,13 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested
|
||||
ho->maxslotindex = MAX_SLOTS - 1;
|
||||
ho->cflag = 1;
|
||||
}
|
||||
IPCPDEBUG((LOG_INFO,
|
||||
IPCPDEBUG(LOG_INFO, (
|
||||
"ipcp_reqci: received COMPRESSTYPE p=%d old=%d maxslot=%d cflag=%d\n",
|
||||
ho->vj_protocol, ho->old_vj, ho->maxslotindex, ho->cflag));
|
||||
break;
|
||||
|
||||
default:
|
||||
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting unknown CI type %d\n", citype));
|
||||
IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting unknown CI type %d\n", citype));
|
||||
orc = CONFREJ;
|
||||
break;
|
||||
}
|
||||
@@ -1150,7 +1134,7 @@ endswitch:
|
||||
|
||||
if (orc == CONFNAK) { /* Nak this CI? */
|
||||
if (reject_if_disagree) { /* Getting fed up with sending NAKs? */
|
||||
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting too many naks\n"));
|
||||
IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting too many naks\n"));
|
||||
orc = CONFREJ; /* Get tough if so */
|
||||
} else {
|
||||
if (rc == CONFREJ) { /* Rejecting prior CI? */
|
||||
@@ -1187,7 +1171,7 @@ endswitch:
|
||||
*/
|
||||
if (rc != CONFREJ && !ho->neg_addr &&
|
||||
wo->req_addr && !reject_if_disagree) {
|
||||
IPCPDEBUG((LOG_INFO, "ipcp_reqci: Requesting peer address\n"));
|
||||
IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Requesting peer address\n"));
|
||||
if (rc == CONFACK) {
|
||||
rc = CONFNAK;
|
||||
ucp = inp; /* reset pointer */
|
||||
@@ -1200,7 +1184,7 @@ endswitch:
|
||||
}
|
||||
|
||||
*len = (int)(ucp - inp); /* Compute output length */
|
||||
IPCPDEBUG((LOG_INFO, "ipcp_reqci: returning Configure-%s\n", CODENAME(rc)));
|
||||
IPCPDEBUG(LOG_INFO, ("ipcp_reqci: returning Configure-%s\n", CODENAME(rc)));
|
||||
return (rc); /* Return final code */
|
||||
}
|
||||
|
||||
@@ -1241,7 +1225,7 @@ ipcp_up(fsm *f)
|
||||
ipcp_options *wo = &ipcp_wantoptions[f->unit];
|
||||
|
||||
np_up(f->unit, PPP_IP);
|
||||
IPCPDEBUG((LOG_INFO, "ipcp: up\n"));
|
||||
IPCPDEBUG(LOG_INFO, ("ipcp: up\n"));
|
||||
|
||||
/*
|
||||
* We must have a non-zero IP address for both ends of the link.
|
||||
@@ -1251,12 +1235,12 @@ ipcp_up(fsm *f)
|
||||
}
|
||||
|
||||
if (ho->hisaddr == 0) {
|
||||
IPCPDEBUG((LOG_ERR, "Could not determine remote IP address\n"));
|
||||
IPCPDEBUG(LOG_ERR, ("Could not determine remote IP address\n"));
|
||||
ipcp_close(f->unit, "Could not determine remote IP address");
|
||||
return;
|
||||
}
|
||||
if (go->ouraddr == 0) {
|
||||
IPCPDEBUG((LOG_ERR, "Could not determine local IP address\n"));
|
||||
IPCPDEBUG(LOG_ERR, ("Could not determine local IP address\n"));
|
||||
ipcp_close(f->unit, "Could not determine local IP address");
|
||||
return;
|
||||
}
|
||||
@@ -1269,7 +1253,7 @@ ipcp_up(fsm *f)
|
||||
* Check that the peer is allowed to use the IP address it wants.
|
||||
*/
|
||||
if (!auth_ip_addr(f->unit, ho->hisaddr)) {
|
||||
IPCPDEBUG((LOG_ERR, "Peer is not authorized to use remote address %s\n",
|
||||
IPCPDEBUG(LOG_ERR, ("Peer is not authorized to use remote address %s\n",
|
||||
inet_ntoa(ho->hisaddr)));
|
||||
ipcp_close(f->unit, "Unauthorized remote IP address");
|
||||
return;
|
||||
@@ -1284,14 +1268,14 @@ ipcp_up(fsm *f)
|
||||
mask = GetMask(go->ouraddr);
|
||||
|
||||
if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask, go->dnsaddr[0], go->dnsaddr[1])) {
|
||||
IPCPDEBUG((LOG_WARNING, "sifaddr failed\n"));
|
||||
IPCPDEBUG(LOG_WARNING, ("sifaddr failed\n"));
|
||||
ipcp_close(f->unit, "Interface configuration failed");
|
||||
return;
|
||||
}
|
||||
|
||||
/* bring the interface up for IP */
|
||||
if (!sifup(f->unit)) {
|
||||
IPCPDEBUG((LOG_WARNING, "sifup failed\n"));
|
||||
IPCPDEBUG(LOG_WARNING, ("sifup failed\n"));
|
||||
ipcp_close(f->unit, "Interface configuration failed");
|
||||
return;
|
||||
}
|
||||
@@ -1305,13 +1289,13 @@ ipcp_up(fsm *f)
|
||||
}
|
||||
}
|
||||
|
||||
IPCPDEBUG((LOG_NOTICE, "local IP address %s\n", inet_ntoa(go->ouraddr)));
|
||||
IPCPDEBUG((LOG_NOTICE, "remote IP address %s\n", inet_ntoa(ho->hisaddr)));
|
||||
IPCPDEBUG(LOG_NOTICE, ("local IP address %s\n", inet_ntoa(go->ouraddr)));
|
||||
IPCPDEBUG(LOG_NOTICE, ("remote IP address %s\n", inet_ntoa(ho->hisaddr)));
|
||||
if (go->dnsaddr[0]) {
|
||||
IPCPDEBUG((LOG_NOTICE, "primary DNS address %s\n", inet_ntoa(go->dnsaddr[0])));
|
||||
IPCPDEBUG(LOG_NOTICE, ("primary DNS address %s\n", inet_ntoa(go->dnsaddr[0])));
|
||||
}
|
||||
if (go->dnsaddr[1]) {
|
||||
IPCPDEBUG((LOG_NOTICE, "secondary DNS address %s\n", inet_ntoa(go->dnsaddr[1])));
|
||||
IPCPDEBUG(LOG_NOTICE, ("secondary DNS address %s\n", inet_ntoa(go->dnsaddr[1])));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1325,7 +1309,7 @@ ipcp_up(fsm *f)
|
||||
static void
|
||||
ipcp_down(fsm *f)
|
||||
{
|
||||
IPCPDEBUG((LOG_INFO, "ipcp: down\n"));
|
||||
IPCPDEBUG(LOG_INFO, ("ipcp: down\n"));
|
||||
np_down(f->unit, PPP_IP);
|
||||
sifvjcomp(f->unit, 0, 0, 0);
|
||||
|
||||
@@ -1361,7 +1345,7 @@ ipcp_finished(fsm *f)
|
||||
np_finished(f->unit, PPP_IP);
|
||||
}
|
||||
|
||||
#if 0
|
||||
#if PPP_ADDITIONAL_CALLBACKS
|
||||
static int
|
||||
ipcp_printpkt(u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg)
|
||||
{
|
||||
@@ -1422,6 +1406,6 @@ ip_active_pkt(u_char *pkt, int len)
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
#endif /* PPP_ADDITIONAL_CALLBACKS */
|
||||
|
||||
#endif /* PPP_SUPPORT */
|
||||
|
||||
@@ -48,15 +48,12 @@
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id: ipcp.h,v 1.3 2007/12/19 20:47:23 fbernon Exp $
|
||||
* $Id: ipcp.h,v 1.4 2010/01/18 20:49:43 goldsimon Exp $
|
||||
*/
|
||||
|
||||
#ifndef IPCP_H
|
||||
#define IPCP_H
|
||||
|
||||
/*************************
|
||||
*** PUBLIC DEFINITIONS ***
|
||||
*************************/
|
||||
/*
|
||||
* Options.
|
||||
*/
|
||||
@@ -64,10 +61,10 @@
|
||||
#define CI_COMPRESSTYPE 2 /* Compression Type */
|
||||
#define CI_ADDR 3
|
||||
|
||||
#define CI_MS_WINS1 128 /* Primary WINS value */
|
||||
#define CI_MS_DNS1 129 /* Primary DNS value */
|
||||
#define CI_MS_WINS2 130 /* Secondary WINS value */
|
||||
#define CI_MS_WINS1 128 /* Primary WINS value */
|
||||
#define CI_MS_DNS2 131 /* Secondary DNS value */
|
||||
#define CI_MS_WINS2 130 /* Secondary WINS value */
|
||||
|
||||
#define IPCP_VJMODE_OLD 1 /* "old" mode (option # = 0x0037) */
|
||||
#define IPCP_VJMODE_RFC1172 2 /* "old-rfc"mode (option # = 0x002d) */
|
||||
@@ -78,11 +75,6 @@
|
||||
#define IPCP_VJ_COMP_OLD 0x0037 /* "old" (i.e, broken) value for VJ */
|
||||
/* compression option */
|
||||
|
||||
|
||||
/************************
|
||||
*** PUBLIC DATA TYPES ***
|
||||
************************/
|
||||
|
||||
typedef struct ipcp_options {
|
||||
u_int neg_addr : 1; /* Negotiate IP Address? */
|
||||
u_int old_addrs : 1; /* Use old (IP-Addresses) option? */
|
||||
@@ -103,11 +95,6 @@ typedef struct ipcp_options {
|
||||
u32_t winsaddr[2]; /* Primary and secondary MS WINS entries */
|
||||
} ipcp_options;
|
||||
|
||||
|
||||
/*****************************
|
||||
*** PUBLIC DATA STRUCTURES ***
|
||||
*****************************/
|
||||
|
||||
extern fsm ipcp_fsm[];
|
||||
extern ipcp_options ipcp_wantoptions[];
|
||||
extern ipcp_options ipcp_gotoptions[];
|
||||
@@ -116,9 +103,4 @@ extern ipcp_options ipcp_hisoptions[];
|
||||
|
||||
extern struct protent ipcp_protent;
|
||||
|
||||
|
||||
/***********************
|
||||
*** PUBLIC FUNCTIONS ***
|
||||
***********************/
|
||||
|
||||
#endif /* IPCP_H */
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
|
||||
#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
|
||||
|
||||
#include "ppp.h"
|
||||
#include "ppp_impl.h"
|
||||
#include "pppdebug.h"
|
||||
|
||||
#include "fsm.h"
|
||||
@@ -72,25 +72,43 @@
|
||||
#define PPPOE_MAXMTU PPP_MAXMRU
|
||||
#endif
|
||||
|
||||
|
||||
/*************************/
|
||||
/*** LOCAL DEFINITIONS ***/
|
||||
/*************************/
|
||||
#if 0 /* UNUSED */
|
||||
/*
|
||||
* Length of each type of configuration option (in octets)
|
||||
* LCP-related command-line options.
|
||||
*/
|
||||
#define CILEN_VOID 2
|
||||
#define CILEN_CHAR 3
|
||||
#define CILEN_SHORT 4 /* CILEN_VOID + sizeof(short) */
|
||||
#define CILEN_CHAP 5 /* CILEN_VOID + sizeof(short) + 1 */
|
||||
#define CILEN_LONG 6 /* CILEN_VOID + sizeof(long) */
|
||||
#define CILEN_LQR 8 /* CILEN_VOID + sizeof(short) + sizeof(long) */
|
||||
#define CILEN_CBCP 3
|
||||
int lcp_echo_interval = 0; /* Interval between LCP echo-requests */
|
||||
int lcp_echo_fails = 0; /* Tolerance to unanswered echo-requests */
|
||||
bool lax_recv = 0; /* accept control chars in asyncmap */
|
||||
|
||||
static int setescape (char **);
|
||||
|
||||
static option_t lcp_option_list[] = {
|
||||
/* LCP options */
|
||||
/* list stripped for simplicity */
|
||||
{NULL}
|
||||
};
|
||||
#endif /* UNUSED */
|
||||
|
||||
/* options */
|
||||
LinkPhase lcp_phase[NUM_PPP]; /* Phase of link session (RFC 1661) */
|
||||
static u_int lcp_echo_interval = LCP_ECHOINTERVAL; /* Interval between LCP echo-requests */
|
||||
static u_int lcp_echo_fails = LCP_MAXECHOFAILS; /* Tolerance to unanswered echo-requests */
|
||||
|
||||
/* global vars */
|
||||
static fsm lcp_fsm[NUM_PPP]; /* LCP fsm structure (global)*/
|
||||
lcp_options lcp_wantoptions[NUM_PPP]; /* Options that we want to request */
|
||||
lcp_options lcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
|
||||
lcp_options lcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
|
||||
lcp_options lcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
|
||||
ext_accm xmit_accm[NUM_PPP]; /* extended transmit ACCM */
|
||||
|
||||
static u32_t lcp_echos_pending = 0; /* Number of outstanding echo msgs */
|
||||
static u32_t lcp_echo_number = 0; /* ID number of next echo frame */
|
||||
static u32_t lcp_echo_timer_running = 0; /* TRUE if a timer is running */
|
||||
|
||||
/* @todo: do we really need such a large buffer? The typical 1500 bytes seem too much. */
|
||||
static u_char nak_buffer[PPP_MRU]; /* where we construct a nak packet */
|
||||
|
||||
/***********************************/
|
||||
/*** LOCAL FUNCTION DECLARATIONS ***/
|
||||
/***********************************/
|
||||
/*
|
||||
* Callbacks for fsm code. (CI = Configuration Information)
|
||||
*/
|
||||
@@ -106,12 +124,12 @@ static void lcp_down (fsm*); /* We're DOWN */
|
||||
static void lcp_starting (fsm*); /* We need lower layer up */
|
||||
static void lcp_finished (fsm*); /* We need lower layer down */
|
||||
static int lcp_extcode (fsm*, int, u_char, u_char*, int);
|
||||
|
||||
static void lcp_rprotrej (fsm*, u_char*, int);
|
||||
|
||||
/*
|
||||
* routines to send LCP echos to peer
|
||||
*/
|
||||
|
||||
static void lcp_echo_lowerup (int);
|
||||
static void lcp_echo_lowerdown (int);
|
||||
static void LcpEchoTimeout (void*);
|
||||
@@ -120,41 +138,6 @@ static void LcpSendEchoRequest (fsm*);
|
||||
static void LcpLinkFailure (fsm*);
|
||||
static void LcpEchoCheck (fsm*);
|
||||
|
||||
/*
|
||||
* Protocol entry points.
|
||||
* Some of these are called directly.
|
||||
*/
|
||||
static void lcp_input (int, u_char *, int);
|
||||
static void lcp_protrej (int);
|
||||
|
||||
#define CODENAME(x) ((x) == CONFACK ? "ACK" : (x) == CONFNAK ? "NAK" : "REJ")
|
||||
|
||||
|
||||
/******************************/
|
||||
/*** PUBLIC DATA STRUCTURES ***/
|
||||
/******************************/
|
||||
/* global vars */
|
||||
LinkPhase lcp_phase[NUM_PPP]; /* Phase of link session (RFC 1661) */
|
||||
lcp_options lcp_wantoptions[NUM_PPP]; /* Options that we want to request */
|
||||
lcp_options lcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
|
||||
lcp_options lcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
|
||||
lcp_options lcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
|
||||
ext_accm xmit_accm[NUM_PPP]; /* extended transmit ACCM */
|
||||
|
||||
|
||||
|
||||
/*****************************/
|
||||
/*** LOCAL DATA STRUCTURES ***/
|
||||
/*****************************/
|
||||
static fsm lcp_fsm[NUM_PPP]; /* LCP fsm structure (global)*/
|
||||
static u_int lcp_echo_interval = LCP_ECHOINTERVAL; /* Interval between LCP echo-requests */
|
||||
static u_int lcp_echo_fails = LCP_MAXECHOFAILS; /* Tolerance to unanswered echo-requests */
|
||||
static u32_t lcp_echos_pending = 0; /* Number of outstanding echo msgs */
|
||||
static u32_t lcp_echo_number = 0; /* ID number of next echo frame */
|
||||
static u32_t lcp_echo_timer_running = 0; /* TRUE if a timer is running */
|
||||
|
||||
static u_char nak_buffer[PPP_MRU]; /* where we construct a nak packet */
|
||||
|
||||
static fsm_callbacks lcp_callbacks = { /* LCP callback routines */
|
||||
lcp_resetci, /* Reset our Configuration Information */
|
||||
lcp_cilen, /* Length of our Configuration Information */
|
||||
@@ -173,6 +156,14 @@ static fsm_callbacks lcp_callbacks = { /* LCP callback routines */
|
||||
"LCP" /* String name of protocol */
|
||||
};
|
||||
|
||||
/*
|
||||
* Protocol entry points.
|
||||
* Some of these are called directly.
|
||||
*/
|
||||
|
||||
static void lcp_input (int, u_char *, int);
|
||||
static void lcp_protrej (int);
|
||||
|
||||
struct protent lcp_protent = {
|
||||
PPP_LCP,
|
||||
lcp_init,
|
||||
@@ -182,26 +173,66 @@ struct protent lcp_protent = {
|
||||
lcp_lowerdown,
|
||||
lcp_open,
|
||||
lcp_close,
|
||||
#if 0
|
||||
#if PPP_ADDITIONAL_CALLBACKS
|
||||
lcp_printpkt,
|
||||
NULL,
|
||||
#endif
|
||||
#endif /* PPP_ADDITIONAL_CALLBACKS */
|
||||
1,
|
||||
"LCP",
|
||||
#if 0
|
||||
#if PPP_ADDITIONAL_CALLBACKS
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
#endif
|
||||
#endif /* PPP_ADDITIONAL_CALLBACKS */
|
||||
};
|
||||
|
||||
int lcp_loopbackfail = DEFLOOPBACKFAIL;
|
||||
|
||||
/*
|
||||
* Length of each type of configuration option (in octets)
|
||||
*/
|
||||
#define CILEN_VOID 2
|
||||
#define CILEN_CHAR 3
|
||||
#define CILEN_SHORT 4 /* CILEN_VOID + sizeof(short) */
|
||||
#define CILEN_CHAP 5 /* CILEN_VOID + sizeof(short) + 1 */
|
||||
#define CILEN_LONG 6 /* CILEN_VOID + sizeof(long) */
|
||||
#define CILEN_LQR 8 /* CILEN_VOID + sizeof(short) + sizeof(long) */
|
||||
#define CILEN_CBCP 3
|
||||
|
||||
#define CODENAME(x) ((x) == CONFACK ? "ACK" : (x) == CONFNAK ? "NAK" : "REJ")
|
||||
|
||||
#if 0 /* UNUSED */
|
||||
/*
|
||||
* setescape - add chars to the set we escape on transmission.
|
||||
*/
|
||||
static int
|
||||
setescape(argv)
|
||||
char **argv;
|
||||
{
|
||||
int n, ret;
|
||||
char *p, *endp;
|
||||
|
||||
p = *argv;
|
||||
ret = 1;
|
||||
while (*p) {
|
||||
n = strtol(p, &endp, 16);
|
||||
if (p == endp) {
|
||||
option_error("escape parameter contains invalid hex number '%s'", p);
|
||||
return 0;
|
||||
}
|
||||
p = endp;
|
||||
if (n < 0 || n == 0x5E || n > 0xFF) {
|
||||
option_error("can't escape character 0x%x", n);
|
||||
ret = 0;
|
||||
} else
|
||||
xmit_accm[0][n >> 5] |= 1 << (n & 0x1F);
|
||||
while (*p == ',' || *p == ' ')
|
||||
++p;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif /* UNUSED */
|
||||
|
||||
/***********************************/
|
||||
/*** PUBLIC FUNCTION DEFINITIONS ***/
|
||||
/***********************************/
|
||||
/*
|
||||
* lcp_init - Initialize LCP.
|
||||
*/
|
||||
@@ -211,13 +242,13 @@ lcp_init(int unit)
|
||||
fsm *f = &lcp_fsm[unit];
|
||||
lcp_options *wo = &lcp_wantoptions[unit];
|
||||
lcp_options *ao = &lcp_allowoptions[unit];
|
||||
|
||||
|
||||
f->unit = unit;
|
||||
f->protocol = PPP_LCP;
|
||||
f->callbacks = &lcp_callbacks;
|
||||
|
||||
|
||||
fsm_init(f);
|
||||
|
||||
|
||||
wo->passive = 0;
|
||||
wo->silent = 0;
|
||||
wo->restart = 0; /* Set to 1 in kernels or multi-line implementations */
|
||||
@@ -233,7 +264,7 @@ lcp_init(int unit)
|
||||
wo->neg_accompression = 1;
|
||||
wo->neg_lqr = 0; /* no LQR implementation yet */
|
||||
wo->neg_cbcp = 0;
|
||||
|
||||
|
||||
ao->neg_mru = 1;
|
||||
ao->mru = PPP_MAXMRU;
|
||||
ao->neg_asyncmap = 1;
|
||||
@@ -257,7 +288,7 @@ lcp_init(int unit)
|
||||
xmit_accm[unit][1] = (u_char)((ao->asyncmap >> 8) & 0xFF);
|
||||
xmit_accm[unit][2] = (u_char)((ao->asyncmap >> 16) & 0xFF);
|
||||
xmit_accm[unit][3] = (u_char)((ao->asyncmap >> 24) & 0xFF);
|
||||
LCPDEBUG((LOG_INFO, "lcp_init: xmit_accm=%X %X %X %X\n",
|
||||
LCPDEBUG(LOG_INFO, ("lcp_init: xmit_accm=%X %X %X %X\n",
|
||||
xmit_accm[unit][0],
|
||||
xmit_accm[unit][1],
|
||||
xmit_accm[unit][2],
|
||||
@@ -310,7 +341,7 @@ lcp_close(int unit, char *reason)
|
||||
f->state = LS_CLOSED;
|
||||
lcp_finished(f);
|
||||
} else {
|
||||
fsm_close(&lcp_fsm[unit], reason);
|
||||
fsm_close(f, reason);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,7 +368,7 @@ lcp_lowerup(int unit)
|
||||
| ((u_long)xmit_accm[unit][1] << 8)
|
||||
| ((u_long)xmit_accm[unit][2] << 16)
|
||||
| ((u_long)xmit_accm[unit][3] << 24);
|
||||
LCPDEBUG((LOG_INFO, "lcp_lowerup: asyncmap=%X %X %X %X\n",
|
||||
LCPDEBUG(LOG_INFO, ("lcp_lowerup: asyncmap=%X %X %X %X\n",
|
||||
xmit_accm[unit][3],
|
||||
xmit_accm[unit][2],
|
||||
xmit_accm[unit][1],
|
||||
@@ -356,25 +387,7 @@ lcp_lowerdown(int unit)
|
||||
fsm_lowerdown(&lcp_fsm[unit]);
|
||||
}
|
||||
|
||||
/*
|
||||
* lcp_sprotrej - Send a Protocol-Reject for some protocol.
|
||||
*/
|
||||
void
|
||||
lcp_sprotrej(int unit, u_char *p, int len)
|
||||
{
|
||||
/*
|
||||
* Send back the protocol and the information field of the
|
||||
* rejected packet. We only get here if LCP is in the LS_OPENED state.
|
||||
*/
|
||||
|
||||
fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id, p, len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**********************************/
|
||||
/*** LOCAL FUNCTION DEFINITIONS ***/
|
||||
/**********************************/
|
||||
/*
|
||||
* lcp_input - Input LCP packet.
|
||||
*/
|
||||
@@ -404,7 +417,7 @@ lcp_extcode(fsm *f, int code, u_char id, u_char *inp, int len)
|
||||
if (f->state != LS_OPENED) {
|
||||
break;
|
||||
}
|
||||
LCPDEBUG((LOG_INFO, "lcp: Echo-Request, Rcvd id %d\n", id));
|
||||
LCPDEBUG(LOG_INFO, ("lcp: Echo-Request, Rcvd id %d\n", id));
|
||||
magp = inp;
|
||||
PUTLONG(lcp_gotoptions[f->unit].magicnumber, magp);
|
||||
fsm_sdata(f, ECHOREP, id, inp, len);
|
||||
@@ -413,10 +426,10 @@ lcp_extcode(fsm *f, int code, u_char id, u_char *inp, int len)
|
||||
case ECHOREP:
|
||||
lcp_received_echo_reply(f, id, inp, len);
|
||||
break;
|
||||
|
||||
|
||||
case DISCREQ:
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -436,21 +449,21 @@ lcp_rprotrej(fsm *f, u_char *inp, int len)
|
||||
struct protent *protp;
|
||||
u_short prot;
|
||||
|
||||
if (len < sizeof (u_short)) {
|
||||
LCPDEBUG((LOG_INFO, "lcp_rprotrej: Rcvd short Protocol-Reject packet!\n"));
|
||||
if (len < (int)sizeof (u_short)) {
|
||||
LCPDEBUG(LOG_INFO, ("lcp_rprotrej: Rcvd short Protocol-Reject packet!\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
GETSHORT(prot, inp);
|
||||
|
||||
LCPDEBUG((LOG_INFO, "lcp_rprotrej: Rcvd Protocol-Reject packet for %x!\n", prot));
|
||||
LCPDEBUG(LOG_INFO, ("lcp_rprotrej: Rcvd Protocol-Reject packet for %x!\n", prot));
|
||||
|
||||
/*
|
||||
* Protocol-Reject packets received in any state other than the LCP
|
||||
* LS_OPENED state SHOULD be silently discarded.
|
||||
*/
|
||||
if( f->state != LS_OPENED ) {
|
||||
LCPDEBUG((LOG_INFO, "Protocol-Reject discarded: LCP in state %d\n", f->state));
|
||||
LCPDEBUG(LOG_INFO, ("Protocol-Reject discarded: LCP in state %d\n", f->state));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -464,7 +477,7 @@ lcp_rprotrej(fsm *f, u_char *inp, int len)
|
||||
}
|
||||
}
|
||||
|
||||
LCPDEBUG((LOG_WARNING, "Protocol-Reject for unsupported protocol 0x%x\n", prot));
|
||||
LCPDEBUG(LOG_WARNING, ("Protocol-Reject for unsupported protocol 0x%x\n", prot));
|
||||
}
|
||||
|
||||
|
||||
@@ -478,11 +491,26 @@ lcp_protrej(int unit)
|
||||
/*
|
||||
* Can't reject LCP!
|
||||
*/
|
||||
LCPDEBUG((LOG_WARNING, "lcp_protrej: Received Protocol-Reject for LCP!\n"));
|
||||
LCPDEBUG(LOG_WARNING, ("lcp_protrej: Received Protocol-Reject for LCP!\n"));
|
||||
fsm_protreject(&lcp_fsm[unit]);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* lcp_sprotrej - Send a Protocol-Reject for some protocol.
|
||||
*/
|
||||
void
|
||||
lcp_sprotrej(int unit, u_char *p, int len)
|
||||
{
|
||||
/*
|
||||
* Send back the protocol and the information field of the
|
||||
* rejected packet. We only get here if LCP is in the LS_OPENED state.
|
||||
*/
|
||||
|
||||
fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id, p, len);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* lcp_resetci - Reset our CI.
|
||||
*/
|
||||
@@ -500,7 +528,8 @@ lcp_resetci(fsm *f)
|
||||
/*
|
||||
* lcp_cilen - Return length of our CI.
|
||||
*/
|
||||
static int lcp_cilen(fsm *f)
|
||||
static int
|
||||
lcp_cilen(fsm *f)
|
||||
{
|
||||
lcp_options *go = &lcp_gotoptions[f->unit];
|
||||
|
||||
@@ -537,20 +566,20 @@ lcp_addci(fsm *f, u_char *ucp, int *lenp)
|
||||
|
||||
#define ADDCIVOID(opt, neg) \
|
||||
if (neg) { \
|
||||
LCPDEBUG((LOG_INFO, "lcp_addci: opt=%d\n", opt)); \
|
||||
LCPDEBUG(LOG_INFO, ("lcp_addci: opt=%d\n", opt)); \
|
||||
PUTCHAR(opt, ucp); \
|
||||
PUTCHAR(CILEN_VOID, ucp); \
|
||||
}
|
||||
#define ADDCISHORT(opt, neg, val) \
|
||||
if (neg) { \
|
||||
LCPDEBUG((LOG_INFO, "lcp_addci: INT opt=%d %X\n", opt, val)); \
|
||||
LCPDEBUG(LOG_INFO, ("lcp_addci: INT opt=%d %X\n", opt, val)); \
|
||||
PUTCHAR(opt, ucp); \
|
||||
PUTCHAR(CILEN_SHORT, ucp); \
|
||||
PUTSHORT(val, ucp); \
|
||||
}
|
||||
#define ADDCICHAP(opt, neg, val, digest) \
|
||||
if (neg) { \
|
||||
LCPDEBUG((LOG_INFO, "lcp_addci: CHAP opt=%d %X\n", opt, val)); \
|
||||
LCPDEBUG(LOG_INFO, ("lcp_addci: CHAP opt=%d %X\n", opt, val)); \
|
||||
PUTCHAR(opt, ucp); \
|
||||
PUTCHAR(CILEN_CHAP, ucp); \
|
||||
PUTSHORT(val, ucp); \
|
||||
@@ -558,14 +587,14 @@ lcp_addci(fsm *f, u_char *ucp, int *lenp)
|
||||
}
|
||||
#define ADDCILONG(opt, neg, val) \
|
||||
if (neg) { \
|
||||
LCPDEBUG((LOG_INFO, "lcp_addci: L opt=%d %lX\n", opt, val)); \
|
||||
LCPDEBUG(LOG_INFO, ("lcp_addci: L opt=%d %lX\n", opt, val)); \
|
||||
PUTCHAR(opt, ucp); \
|
||||
PUTCHAR(CILEN_LONG, ucp); \
|
||||
PUTLONG(val, ucp); \
|
||||
}
|
||||
#define ADDCILQR(opt, neg, val) \
|
||||
if (neg) { \
|
||||
LCPDEBUG((LOG_INFO, "lcp_addci: LQR opt=%d %lX\n", opt, val)); \
|
||||
LCPDEBUG(LOG_INFO, ("lcp_addci: LQR opt=%d %lX\n", opt, val)); \
|
||||
PUTCHAR(opt, ucp); \
|
||||
PUTCHAR(CILEN_LQR, ucp); \
|
||||
PUTSHORT(PPP_LQR, ucp); \
|
||||
@@ -573,7 +602,7 @@ lcp_addci(fsm *f, u_char *ucp, int *lenp)
|
||||
}
|
||||
#define ADDCICHAR(opt, neg, val) \
|
||||
if (neg) { \
|
||||
LCPDEBUG((LOG_INFO, "lcp_addci: CHAR opt=%d %X '%z'\n", opt, val, val)); \
|
||||
LCPDEBUG(LOG_INFO, ("lcp_addci: CHAR opt=%d %X '%z'\n", opt, val, val)); \
|
||||
PUTCHAR(opt, ucp); \
|
||||
PUTCHAR(CILEN_CHAR, ucp); \
|
||||
PUTCHAR(val, ucp); \
|
||||
@@ -591,7 +620,7 @@ lcp_addci(fsm *f, u_char *ucp, int *lenp)
|
||||
|
||||
if (ucp - start_ucp != *lenp) {
|
||||
/* this should never happen, because peer_mtu should be 1500 */
|
||||
LCPDEBUG((LOG_ERR, "Bug in lcp_addci: wrong length\n"));
|
||||
LCPDEBUG(LOG_ERR, ("Bug in lcp_addci: wrong length\n"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -709,10 +738,10 @@ lcp_ackci(fsm *f, u_char *p, int len)
|
||||
if (len != 0) {
|
||||
goto bad;
|
||||
}
|
||||
LCPDEBUG((LOG_INFO, "lcp_acki: Ack\n"));
|
||||
LCPDEBUG(LOG_INFO, ("lcp_acki: Ack\n"));
|
||||
return (1);
|
||||
bad:
|
||||
LCPDEBUG((LOG_WARNING, "lcp_acki: received bad Ack!\n"));
|
||||
LCPDEBUG(LOG_WARNING, ("lcp_acki: received bad Ack!\n"));
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -1020,7 +1049,7 @@ lcp_nakci(fsm *f, u_char *p, int len)
|
||||
if (f->state != LS_OPENED) {
|
||||
if (looped_back) {
|
||||
if (++try.numloops >= lcp_loopbackfail) {
|
||||
LCPDEBUG((LOG_NOTICE, "Serial line is looped back.\n"));
|
||||
LCPDEBUG(LOG_NOTICE, ("Serial line is looped back.\n"));
|
||||
lcp_close(f->unit, "Loopback detected");
|
||||
}
|
||||
} else {
|
||||
@@ -1032,7 +1061,7 @@ lcp_nakci(fsm *f, u_char *p, int len)
|
||||
return 1;
|
||||
|
||||
bad:
|
||||
LCPDEBUG((LOG_WARNING, "lcp_nakci: received bad Nak!\n"));
|
||||
LCPDEBUG(LOG_WARNING, ("lcp_nakci: received bad Nak!\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1070,7 +1099,7 @@ lcp_rejci(fsm *f, u_char *p, int len)
|
||||
len -= CILEN_VOID; \
|
||||
INCPTR(CILEN_VOID, p); \
|
||||
try.neg = 0; \
|
||||
LCPDEBUG((LOG_INFO, "lcp_rejci: void opt %d rejected\n", opt)); \
|
||||
LCPDEBUG(LOG_INFO, ("lcp_rejci: void opt %d rejected\n", opt)); \
|
||||
}
|
||||
#define REJCISHORT(opt, neg, val) \
|
||||
if (go->neg && \
|
||||
@@ -1085,7 +1114,7 @@ lcp_rejci(fsm *f, u_char *p, int len)
|
||||
goto bad; \
|
||||
} \
|
||||
try.neg = 0; \
|
||||
LCPDEBUG((LOG_INFO,"lcp_rejci: short opt %d rejected\n", opt)); \
|
||||
LCPDEBUG(LOG_INFO, ("lcp_rejci: short opt %d rejected\n", opt)); \
|
||||
}
|
||||
#define REJCICHAP(opt, neg, val, digest) \
|
||||
if (go->neg && \
|
||||
@@ -1102,7 +1131,7 @@ lcp_rejci(fsm *f, u_char *p, int len)
|
||||
} \
|
||||
try.neg = 0; \
|
||||
try.neg_upap = 0; \
|
||||
LCPDEBUG((LOG_INFO,"lcp_rejci: chap opt %d rejected\n", opt)); \
|
||||
LCPDEBUG(LOG_INFO, ("lcp_rejci: chap opt %d rejected\n", opt)); \
|
||||
}
|
||||
#define REJCILONG(opt, neg, val) \
|
||||
if (go->neg && \
|
||||
@@ -1117,7 +1146,7 @@ lcp_rejci(fsm *f, u_char *p, int len)
|
||||
goto bad; \
|
||||
} \
|
||||
try.neg = 0; \
|
||||
LCPDEBUG((LOG_INFO,"lcp_rejci: long opt %d rejected\n", opt)); \
|
||||
LCPDEBUG(LOG_INFO, ("lcp_rejci: long opt %d rejected\n", opt)); \
|
||||
}
|
||||
#define REJCILQR(opt, neg, val) \
|
||||
if (go->neg && \
|
||||
@@ -1133,7 +1162,7 @@ lcp_rejci(fsm *f, u_char *p, int len)
|
||||
goto bad; \
|
||||
} \
|
||||
try.neg = 0; \
|
||||
LCPDEBUG((LOG_INFO,"lcp_rejci: LQR opt %d rejected\n", opt)); \
|
||||
LCPDEBUG(LOG_INFO, ("lcp_rejci: LQR opt %d rejected\n", opt)); \
|
||||
}
|
||||
#define REJCICBCP(opt, neg, val) \
|
||||
if (go->neg && \
|
||||
@@ -1148,7 +1177,7 @@ lcp_rejci(fsm *f, u_char *p, int len)
|
||||
goto bad; \
|
||||
} \
|
||||
try.neg = 0; \
|
||||
LCPDEBUG((LOG_INFO,"lcp_rejci: Callback opt %d rejected\n", opt)); \
|
||||
LCPDEBUG(LOG_INFO, ("lcp_rejci: Callback opt %d rejected\n", opt)); \
|
||||
}
|
||||
|
||||
REJCISHORT(CI_MRU, neg_mru, go->mru);
|
||||
@@ -1178,7 +1207,7 @@ lcp_rejci(fsm *f, u_char *p, int len)
|
||||
return 1;
|
||||
|
||||
bad:
|
||||
LCPDEBUG((LOG_WARNING, "lcp_rejci: received bad Reject!\n"));
|
||||
LCPDEBUG(LOG_WARNING, ("lcp_rejci: received bad Reject!\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1200,7 +1229,8 @@ lcp_reqci(fsm *f,
|
||||
lcp_options *ho = &lcp_hisoptions[f->unit];
|
||||
lcp_options *ao = &lcp_allowoptions[f->unit];
|
||||
u_char *cip, *next; /* Pointer to current and next CIs */
|
||||
int cilen, citype, cichar; /* Parsed len, type, char value */
|
||||
int cilen, citype; /* Parsed len, type */
|
||||
u_char cichar; /* Parsed char value */
|
||||
u_short cishort; /* Parsed short value */
|
||||
u32_t cilong; /* Parse long value */
|
||||
int rc = CONFACK; /* Final packet return code */
|
||||
@@ -1211,7 +1241,7 @@ lcp_reqci(fsm *f,
|
||||
int l = *lenp; /* Length left */
|
||||
#if TRACELCP > 0
|
||||
char traceBuf[80];
|
||||
int traceNdx = 0;
|
||||
size_t traceNdx = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -1231,7 +1261,7 @@ lcp_reqci(fsm *f,
|
||||
if (l < 2 || /* Not enough data for CI header or */
|
||||
p[1] < 2 || /* CI length too small or */
|
||||
p[1] > l) { /* CI length too big? */
|
||||
LCPDEBUG((LOG_WARNING, "lcp_reqci: bad CI length!\n"));
|
||||
LCPDEBUG(LOG_WARNING, ("lcp_reqci: bad CI length!\n"));
|
||||
orc = CONFREJ; /* Reject bad CI */
|
||||
cilen = l; /* Reject till end of packet */
|
||||
l = 0; /* Don't loop again */
|
||||
@@ -1246,11 +1276,11 @@ lcp_reqci(fsm *f,
|
||||
switch (citype) { /* Check CI type */
|
||||
case CI_MRU:
|
||||
if (!ao->neg_mru) { /* Allow option? */
|
||||
LCPDEBUG((LOG_INFO, "lcp_reqci: Reject MRU - not allowed\n"));
|
||||
LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject MRU - not allowed\n"));
|
||||
orc = CONFREJ; /* Reject CI */
|
||||
break;
|
||||
} else if (cilen != CILEN_SHORT) { /* Check CI length */
|
||||
LCPDEBUG((LOG_INFO, "lcp_reqci: Reject MRU - bad length\n"));
|
||||
LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject MRU - bad length\n"));
|
||||
orc = CONFREJ; /* Reject CI */
|
||||
break;
|
||||
}
|
||||
@@ -1262,7 +1292,7 @@ lcp_reqci(fsm *f,
|
||||
* we'll just ignore it.
|
||||
*/
|
||||
if (cishort < PPP_MINMRU) {
|
||||
LCPDEBUG((LOG_INFO, "lcp_reqci: Nak - MRU too small\n"));
|
||||
LCPDEBUG(LOG_INFO, ("lcp_reqci: Nak - MRU too small\n"));
|
||||
orc = CONFNAK; /* Nak CI */
|
||||
PUTCHAR(CI_MRU, nakp);
|
||||
PUTCHAR(CILEN_SHORT, nakp);
|
||||
@@ -1279,11 +1309,11 @@ lcp_reqci(fsm *f,
|
||||
|
||||
case CI_ASYNCMAP:
|
||||
if (!ao->neg_asyncmap) {
|
||||
LCPDEBUG((LOG_INFO, "lcp_reqci: Reject ASYNCMAP not allowed\n"));
|
||||
LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject ASYNCMAP not allowed\n"));
|
||||
orc = CONFREJ;
|
||||
break;
|
||||
} else if (cilen != CILEN_LONG) {
|
||||
LCPDEBUG((LOG_INFO, "lcp_reqci: Reject ASYNCMAP bad length\n"));
|
||||
LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject ASYNCMAP bad length\n"));
|
||||
orc = CONFREJ;
|
||||
break;
|
||||
}
|
||||
@@ -1294,7 +1324,7 @@ lcp_reqci(fsm *f,
|
||||
* which are set in lcp_allowoptions[unit].asyncmap.
|
||||
*/
|
||||
if ((ao->asyncmap & ~cilong) != 0) {
|
||||
LCPDEBUG((LOG_INFO, "lcp_reqci: Nak ASYNCMAP %lX missing %lX\n",
|
||||
LCPDEBUG(LOG_INFO, ("lcp_reqci: Nak ASYNCMAP %lX missing %lX\n",
|
||||
cilong, ao->asyncmap));
|
||||
orc = CONFNAK;
|
||||
PUTCHAR(CI_ASYNCMAP, nakp);
|
||||
@@ -1312,14 +1342,14 @@ lcp_reqci(fsm *f,
|
||||
|
||||
case CI_AUTHTYPE:
|
||||
if (cilen < CILEN_SHORT) {
|
||||
LCPDEBUG((LOG_INFO, "lcp_reqci: Reject AUTHTYPE missing arg\n"));
|
||||
LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject AUTHTYPE missing arg\n"));
|
||||
orc = CONFREJ;
|
||||
break;
|
||||
} else if (!(ao->neg_upap || ao->neg_chap)) {
|
||||
/*
|
||||
* Reject the option if we're not willing to authenticate.
|
||||
*/
|
||||
LCPDEBUG((LOG_INFO, "lcp_reqci: Reject AUTHTYPE not allowed\n"));
|
||||
LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject AUTHTYPE not allowed\n"));
|
||||
orc = CONFREJ;
|
||||
break;
|
||||
}
|
||||
@@ -1338,16 +1368,16 @@ lcp_reqci(fsm *f,
|
||||
|
||||
if (cishort == PPP_PAP) {
|
||||
if (ho->neg_chap) { /* we've already accepted CHAP */
|
||||
LCPDEBUG((LOG_WARNING, "lcp_reqci: Reject AUTHTYPE PAP already accepted\n"));
|
||||
LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE PAP already accepted\n"));
|
||||
orc = CONFREJ;
|
||||
break;
|
||||
} else if (cilen != CILEN_SHORT) {
|
||||
LCPDEBUG((LOG_WARNING, "lcp_reqci: Reject AUTHTYPE PAP bad len\n"));
|
||||
LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE PAP bad len\n"));
|
||||
orc = CONFREJ;
|
||||
break;
|
||||
}
|
||||
if (!ao->neg_upap) { /* we don't want to do PAP */
|
||||
LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE PAP not allowed\n"));
|
||||
LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE PAP not allowed\n"));
|
||||
orc = CONFNAK; /* NAK it and suggest CHAP */
|
||||
PUTCHAR(CI_AUTHTYPE, nakp);
|
||||
PUTCHAR(CILEN_CHAP, nakp);
|
||||
@@ -1364,16 +1394,16 @@ lcp_reqci(fsm *f,
|
||||
}
|
||||
if (cishort == PPP_CHAP) {
|
||||
if (ho->neg_upap) { /* we've already accepted PAP */
|
||||
LCPDEBUG((LOG_WARNING, "lcp_reqci: Reject AUTHTYPE CHAP accepted PAP\n"));
|
||||
LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE CHAP accepted PAP\n"));
|
||||
orc = CONFREJ;
|
||||
break;
|
||||
} else if (cilen != CILEN_CHAP) {
|
||||
LCPDEBUG((LOG_WARNING, "lcp_reqci: Reject AUTHTYPE CHAP bad len\n"));
|
||||
LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE CHAP bad len\n"));
|
||||
orc = CONFREJ;
|
||||
break;
|
||||
}
|
||||
if (!ao->neg_chap) { /* we don't want to do CHAP */
|
||||
LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE CHAP not allowed\n"));
|
||||
LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE CHAP not allowed\n"));
|
||||
orc = CONFNAK; /* NAK it and suggest PAP */
|
||||
PUTCHAR(CI_AUTHTYPE, nakp);
|
||||
PUTCHAR(CILEN_SHORT, nakp);
|
||||
@@ -1382,11 +1412,11 @@ lcp_reqci(fsm *f,
|
||||
}
|
||||
GETCHAR(cichar, p); /* get digest type*/
|
||||
if (cichar != CHAP_DIGEST_MD5
|
||||
#ifdef CHAPMS
|
||||
#if MSCHAP_SUPPORT
|
||||
&& cichar != CHAP_MICROSOFT
|
||||
#endif
|
||||
) {
|
||||
LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE CHAP digest=%d\n", cichar));
|
||||
LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE CHAP digest=%d\n", (int)cichar));
|
||||
orc = CONFNAK;
|
||||
PUTCHAR(CI_AUTHTYPE, nakp);
|
||||
PUTCHAR(CILEN_CHAP, nakp);
|
||||
@@ -1395,7 +1425,7 @@ lcp_reqci(fsm *f,
|
||||
break;
|
||||
}
|
||||
#if TRACELCP > 0
|
||||
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CHAP %X,%d", cishort, cichar);
|
||||
snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CHAP %X,%d", cishort, (int)cichar);
|
||||
traceNdx = strlen(traceBuf);
|
||||
#endif
|
||||
ho->chap_mdtype = cichar; /* save md type */
|
||||
@@ -1411,12 +1441,12 @@ lcp_reqci(fsm *f,
|
||||
orc = CONFNAK;
|
||||
PUTCHAR(CI_AUTHTYPE, nakp);
|
||||
if (ao->neg_chap) {
|
||||
LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE %d req CHAP\n", cishort));
|
||||
LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE %d req CHAP\n", cishort));
|
||||
PUTCHAR(CILEN_CHAP, nakp);
|
||||
PUTSHORT(PPP_CHAP, nakp);
|
||||
PUTCHAR(ao->chap_mdtype, nakp);
|
||||
} else {
|
||||
LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE %d req PAP\n", cishort));
|
||||
LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE %d req PAP\n", cishort));
|
||||
PUTCHAR(CILEN_SHORT, nakp);
|
||||
PUTSHORT(PPP_PAP, nakp);
|
||||
}
|
||||
@@ -1541,7 +1571,7 @@ lcp_reqci(fsm *f,
|
||||
endswitch:
|
||||
#if TRACELCP
|
||||
if (traceNdx >= 80 - 32) {
|
||||
LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd%s\n", traceBuf));
|
||||
LCPDEBUG(LOG_INFO, ("lcp_reqci: rcvd%s\n", traceBuf));
|
||||
traceNdx = 0;
|
||||
}
|
||||
#endif
|
||||
@@ -1595,10 +1625,10 @@ lcp_reqci(fsm *f,
|
||||
|
||||
#if TRACELCP > 0
|
||||
if (traceNdx > 0) {
|
||||
LCPDEBUG((LOG_INFO, "lcp_reqci: %s\n", traceBuf));
|
||||
LCPDEBUG(LOG_INFO, ("lcp_reqci: %s\n", traceBuf));
|
||||
}
|
||||
#endif
|
||||
LCPDEBUG((LOG_INFO, "lcp_reqci: returning CONF%s.\n", CODENAME(rc)));
|
||||
LCPDEBUG(LOG_INFO, ("lcp_reqci: returning CONF%s.\n", CODENAME(rc)));
|
||||
return (rc); /* Return final code */
|
||||
}
|
||||
|
||||
@@ -1645,7 +1675,7 @@ lcp_up(fsm *f)
|
||||
|
||||
lcp_echo_lowerup(f->unit); /* Enable echo messages */
|
||||
|
||||
link_established(f->unit);
|
||||
link_established(f->unit); /* The link is up; authenticate now */
|
||||
}
|
||||
|
||||
|
||||
@@ -1677,7 +1707,7 @@ lcp_down(fsm *f)
|
||||
static void
|
||||
lcp_starting(fsm *f)
|
||||
{
|
||||
link_required(f->unit);
|
||||
link_required(f->unit); /* lwip: currently does nothing */
|
||||
}
|
||||
|
||||
|
||||
@@ -1687,11 +1717,11 @@ lcp_starting(fsm *f)
|
||||
static void
|
||||
lcp_finished(fsm *f)
|
||||
{
|
||||
link_terminated(f->unit);
|
||||
link_terminated(f->unit); /* we are finished with the link */
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
#if PPP_ADDITIONAL_CALLBACKS
|
||||
/*
|
||||
* print_string - print a readable representation of a string using
|
||||
* printer.
|
||||
@@ -1898,7 +1928,7 @@ lcp_printpkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void *
|
||||
|
||||
return (int)(p - pstart);
|
||||
}
|
||||
#endif
|
||||
#endif /* PPP_ADDITIONAL_CALLBACKS */
|
||||
|
||||
/*
|
||||
* Time to shut down the link because there is nothing out there.
|
||||
@@ -1907,8 +1937,8 @@ static void
|
||||
LcpLinkFailure (fsm *f)
|
||||
{
|
||||
if (f->state == LS_OPENED) {
|
||||
LCPDEBUG((LOG_INFO, "No response to %d echo-requests\n", lcp_echos_pending));
|
||||
LCPDEBUG((LOG_NOTICE, "Serial link appears to be disconnected.\n"));
|
||||
LCPDEBUG(LOG_INFO, ("No response to %d echo-requests\n", lcp_echos_pending));
|
||||
LCPDEBUG(LOG_NOTICE, ("Serial link appears to be disconnected.\n"));
|
||||
lcp_close(f->unit, "Peer not responding");
|
||||
}
|
||||
}
|
||||
@@ -1954,15 +1984,15 @@ lcp_received_echo_reply (fsm *f, int id, u_char *inp, int len)
|
||||
|
||||
/* Check the magic number - don't count replies from ourselves. */
|
||||
if (len < 4) {
|
||||
LCPDEBUG((LOG_WARNING, "lcp: received short Echo-Reply, length %d\n", len));
|
||||
LCPDEBUG(LOG_WARNING, ("lcp: received short Echo-Reply, length %d\n", len));
|
||||
return;
|
||||
}
|
||||
GETLONG(magic, inp);
|
||||
if (lcp_gotoptions[f->unit].neg_magicnumber && magic == lcp_gotoptions[f->unit].magicnumber) {
|
||||
LCPDEBUG((LOG_WARNING, "appear to have received our own echo-reply!\n"));
|
||||
LCPDEBUG(LOG_WARNING, ("appear to have received our own echo-reply!\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Reset the number of outstanding echo frames */
|
||||
lcp_echos_pending = 0;
|
||||
}
|
||||
@@ -1980,7 +2010,7 @@ LcpSendEchoRequest (fsm *f)
|
||||
* Detect the failure of the peer at this point.
|
||||
*/
|
||||
if (lcp_echo_fails != 0) {
|
||||
if (lcp_echos_pending++ >= lcp_echo_fails) {
|
||||
if (lcp_echos_pending >= lcp_echo_fails) {
|
||||
LcpLinkFailure(f);
|
||||
lcp_echos_pending = 0;
|
||||
}
|
||||
@@ -1994,6 +2024,7 @@ LcpSendEchoRequest (fsm *f)
|
||||
pktp = pkt;
|
||||
PUTLONG(lcp_magic, pktp);
|
||||
fsm_sdata(f, ECHOREQ, (u_char)(lcp_echo_number++ & 0xFF), pkt, (int)(pktp - pkt));
|
||||
++lcp_echos_pending;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,15 +48,11 @@
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id: lcp.h,v 1.3 2007/12/19 20:47:23 fbernon Exp $
|
||||
* $Id: lcp.h,v 1.4 2010/01/18 20:49:43 goldsimon Exp $
|
||||
*/
|
||||
|
||||
#ifndef LCP_H
|
||||
#define LCP_H
|
||||
|
||||
/*************************
|
||||
*** PUBLIC DEFINITIONS ***
|
||||
*************************/
|
||||
/*
|
||||
* Options.
|
||||
*/
|
||||
@@ -73,7 +69,7 @@
|
||||
#define CI_EPDISC 19 /* endpoint discriminator */
|
||||
|
||||
/*
|
||||
* LCP-specific packet types.
|
||||
* LCP-specific packet types (code numbers).
|
||||
*/
|
||||
#define PROTREJ 8 /* Protocol Reject */
|
||||
#define ECHOREQ 9 /* Echo Request */
|
||||
@@ -81,11 +77,6 @@
|
||||
#define DISCREQ 11 /* Discard Request */
|
||||
#define CBCP_OPT 6 /* Use callback control protocol */
|
||||
|
||||
|
||||
/************************
|
||||
*** PUBLIC DATA TYPES ***
|
||||
************************/
|
||||
|
||||
/*
|
||||
* The state of options is described by an lcp_options structure.
|
||||
*/
|
||||
@@ -135,9 +126,6 @@ typedef enum {
|
||||
} LinkPhase;
|
||||
|
||||
|
||||
/*****************************
|
||||
*** PUBLIC DATA STRUCTURES ***
|
||||
*****************************/
|
||||
|
||||
extern LinkPhase lcp_phase[NUM_PPP]; /* Phase of link session (RFC 1661) */
|
||||
extern lcp_options lcp_wantoptions[];
|
||||
@@ -147,10 +135,6 @@ extern lcp_options lcp_hisoptions[];
|
||||
extern ext_accm xmit_accm[];
|
||||
|
||||
|
||||
/***********************
|
||||
*** PUBLIC FUNCTIONS ***
|
||||
***********************/
|
||||
|
||||
void lcp_init (int);
|
||||
void lcp_open (int);
|
||||
void lcp_close (int, char *);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user