A userspace application that filters DHCP floods to protect a DHCP server. It uses the Netfilter userspace packet queuing API.
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include "dp_dhcpv4.h"
  4. #include "dp_helpers.h"
  5. void dp_dhcpv4_check(dp_conf *conf, unsigned char *pkt, int pktlen, int offset, unsigned char **remoteid, int *remoteidlen) {
  6. int hwaddrpos = offset + 28; // remember where the hw addr is if we need to fallback to it
  7. int hwlenpos = offset + 2; // remember where the hw addr len is if we need to fallback to it
  8. // jump DHCP header
  9. offset += 28 + 16 + 64 + 128;
  10. // minimum packet size, fixed header + magic cookie (4 octets)
  11. if ( pktlen < offset + 4 ) {
  12. if ( conf->debug ) printf("packet too small\n");
  13. return;
  14. }
  15. // check magic cookie
  16. if ( pkt[offset] != 99 || pkt[offset+1] != 130 || pkt[offset+2] != 83 || pkt[offset+3] != 99 ) {
  17. if ( conf->debug )
  18. printf(
  19. "invalid magic cookie %02x%02x%02x%02x\n",
  20. pkt[offset], pkt[offset+1],
  21. pkt[offset+2], pkt[offset+3]);
  22. return;
  23. }
  24. offset+=4;
  25. // parse TLV options
  26. while(offset<pktlen && remoteidlen==0) {
  27. uint8_t type = pkt[offset];
  28. uint8_t len;
  29. offset++;
  30. // padding of 1 octet
  31. if ( type == 0 ) {
  32. continue;
  33. }
  34. // end of options
  35. if ( type == 255 )
  36. break;
  37. // make sure we can read len
  38. if ( offset>=pktlen )
  39. break;
  40. len = pkt[offset];
  41. offset++;
  42. // can the value be read
  43. if ( offset+len>pktlen )
  44. break;
  45. // option 82 parser
  46. if ( type == 82 ) {
  47. unsigned char *o82 = pkt+offset;
  48. int o82off = 0;
  49. // loop until the end, +2 to ensure we can read type and length
  50. while(o82off+2<len && remoteidlen==0) {
  51. uint8_t otype = o82[o82off];
  52. uint8_t olen = o82[o82off+1];
  53. o82off+=2;
  54. // printf("o82 type=%i len=%i\n", otype, olen);
  55. // remoteid
  56. if ( otype == 2 ) {
  57. // make sure we don't overflow and can read all data
  58. if ( o82off + olen > len ) {
  59. if ( conf->debug) printf("option 82.2 data too long\n");
  60. break;
  61. }
  62. else {
  63. *remoteid = o82 + o82off;
  64. *remoteidlen = olen;
  65. }
  66. }
  67. o82off+=olen;
  68. }
  69. }
  70. offset+=len;
  71. }
  72. // if we didn't find opt82.2, we fallback to the hw addr
  73. if ( *remoteidlen == 0 ) {
  74. // nope, we won't overflow
  75. if ( (uint8_t)pkt[hwlenpos] <= 16 ) {
  76. *remoteid = pkt+hwaddrpos;
  77. *remoteidlen = (uint8_t)pkt[hwlenpos];
  78. }
  79. }
  80. }