Bläddra i källkod

support for dhcpv6

tags/v1.0.0
Pascal Gloor 5 år sedan
förälder
incheckning
9ddbb7722f
1 ändrade filer med 81 tillägg och 42 borttagningar
  1. 81
    42
      dhcp_protect.c

+ 81
- 42
dhcp_protect.c Visa fil

@@ -205,15 +205,6 @@ int dhcp_check(struct nfq_data *nfa, dp_conf *conf) {

if ( conf->debug ) printf("got a packet, len = %i\n", pktlen);

/* a bit too much ;)
if ( conf->debug ) {
for(i=0; i<pktlen; i++) {
if ( !(i%16) ) printf("\n");
printf("%02x ", pkt[i]);
}
}
*/

// can we read the IP proto and IP header length ?
if ( pktlen > 0 ) {
ipver = pkt[offset];
@@ -221,25 +212,89 @@ int dhcp_check(struct nfq_data *nfa, dp_conf *conf) {
ihl = pkt[offset];
ihl &= 0x0f;

if ( ipver != 4 ) {
if ( ipver == 4 ) {
// jump to DHCPv4
offset += ( ihl * 4 ) + 8;
dhcpv4_check(conf, pkt, pktlen, offset, &remoteid, &remoteidlen);
}
else if ( ipver == 6 ) {
// jump to DHCPv6
offset += 48 + 8;
dhcpv6_check(conf, pkt, pktlen, offset, &remoteid, &remoteidlen);
}
else {
if ( conf->debug ) printf("not an IPv4 packet\n");
rv = NF_ACCEPT;
goto end;
}
}

// jump over the IPv4 header
offset += ihl * 4;
if ( remoteidlen>0 ) {
// count the packet, even when blacklisted.
dp_accounting_add(conf, remoteid, remoteidlen);

// check if already in the blacklist
if ( dp_blacklist_check(conf, remoteid, remoteidlen) == NF_DROP )
rv = NF_DROP;

// check if it must be added to the blacklist
else if ( dp_accounting_check(conf, remoteid, remoteidlen) == NF_DROP ) {
dp_blacklist_add(conf, remoteid, remoteidlen);
rv = NF_DROP;
}
}

end:

dp_hash_cleanup(conf);

// jump over UDP + DHCP header
offset += 8 + 28 + 16 + 64 + 128;
return rv;
}

void dhcpv6_check(dp_conf *conf, unsigned char *pkt, int pktlen, int offset, unsigned char *remoteid, int *remoteidlen) {

while(offset<pktlen) {
uint8_t msgtype = (uint8_t)pkt[offset];

switch(msgtype) {
case 11: // RELAY-FORW
case 12: // RELAY-REPL
offset += 2 + 16 + 16; // msg-type, hop-count, link-addr, peer-addr
break;
default: // all other msgtypes
offset += 2; // msg-type, hop-count
}

while(offset+1<pktlen) {
uint8_t code = (uint8_t)pkt[offset];
uint8_t len = (uint8_t)pkt[offset+1];

offset+2;

if ( code == 1 ) { // Client identifier / DUID
remoteid = pkt+offset;
*remoteidlen = len;
break;
}
offset+=len;
}

if ( *remoteidlen>0 )
break;
}
}


void dhcpv4_check(dp_conf *conf, unsigned char *pkt, int pktlen, int offset, unsigned char *remoteid, int *remoteidlen) {
int hwaddrpos = offset + 28; // remember where the hw addr is if we need to fallback to it
int hwlenpos = offset + 2; // remember where the hw addr len is if we need to fallback to it

// jump DHCP header
offset += 28 + 16 + 64 + 128;

// minimum packet size, fixed header + magic cookie (4 octets)
if ( pktlen < offset + 4 ) {
if ( conf->debug ) printf("packet too small\n");
rv = NF_ACCEPT;
goto end;
return;
}

// check magic cookie
@@ -249,9 +304,7 @@ int dhcp_check(struct nfq_data *nfa, dp_conf *conf) {
"invalid magic cookie %02x%02x%02x%02x\n",
pkt[offset], pkt[offset+1],
pkt[offset+2], pkt[offset+3]);

rv = NF_ACCEPT;
goto end;
return;
}
offset+=4;

@@ -301,13 +354,11 @@ int dhcp_check(struct nfq_data *nfa, dp_conf *conf) {
// make sure we don't overflow and can read all data
if ( o82off + olen > len ) {
if ( conf->debug) printf("option 82.2 data too long\n");
rv = NF_ACCEPT;
goto end;
break;
}
else {
remoteid = o82 + o82off;
remoteidlen = olen;
found=1;
*remoteidlen = olen;
}
}

@@ -318,26 +369,14 @@ int dhcp_check(struct nfq_data *nfa, dp_conf *conf) {
offset+=len;
}

if ( found ) {
// count the packet, even when blacklisted.
dp_accounting_add(conf, remoteid, remoteidlen);

// check if already in the blacklist
if ( dp_blacklist_check(conf, remoteid, remoteidlen) == NF_DROP )
rv = NF_DROP;

// check if it must be added to the blacklist
else if ( dp_accounting_check(conf, remoteid, remoteidlen) == NF_DROP ) {
dp_blacklist_add(conf, remoteid, remoteidlen);
rv = NF_DROP;
// if we didn't find opt82.2, we fallback to the hw addr
if ( *remoteidlen == 0 ) {
// nope, we won't overflow
if ( (uint8_t)pkt[hwlenpos] <= 16 ) {
remoteid = pkt+hwaddrpos;
remoteidlen = (uint8_t)pkt[hwlenpos];
}
}

end:

dp_hash_cleanup(conf);

return rv;
}

// netfilter queue callback

Laddar…
Avbryt
Spara