A userspace application that filters DHCP floods to protect a DHCP server. It uses the Netfilter userspace packet queuing API.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

dp_dhcpv4.c 2.2KB

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. }