int write_arp(int action, u_char * var_val, u_char var_val_type, size_t var_val_len, u_char * statP, oid * name, size_t length) { int var, retval = SNMP_ERR_NOERROR; static PMIB_IPNETROW oldarp_row = NULL; MIB_IPNETROW temp_row; DWORD status = NO_ERROR; /* * IP Net to Media table object identifier is of form: * 1.3.6.1.2.1.4.22.1.?.interface.A.B.C.D, where A.B.C.D is IP address. * Interface is at offset 10, * IPADDR starts at offset 11. */ if (name[6] == 3) { /* AT group oid */ if (length != 16) { snmp_log(LOG_ERR, "length error\n"); return SNMP_ERR_NOCREATION; } } else { /* IP NetToMedia group oid */ if (length != 15) { snmp_log(LOG_ERR, "length error\n"); return SNMP_ERR_NOCREATION; } } /* * #define for ipNetToMediaTable entries are 1 less than corresponding sub-id in MIB * * i.e. IPMEDIAIFINDEX defined as 0, but ipNetToMediaIfIndex registered as 1 */ var = name[9] - 1; switch (action) { case RESERVE1: switch (var) { case IPMEDIAIFINDEX: if (var_val_type != ASN_INTEGER) { snmp_log(LOG_ERR, "not integer\n"); return SNMP_ERR_WRONGTYPE; } if ((*((int *) var_val)) < 0) { snmp_log(LOG_ERR, "invalid media ifIndex"); return SNMP_ERR_WRONGVALUE; } if (var_val_len > sizeof(int)) { snmp_log(LOG_ERR, "bad length\n"); return SNMP_ERR_WRONGLENGTH; } break; case IPMEDIANETADDRESS: if (var_val_type != ASN_IPADDRESS) { snmp_log(LOG_ERR, "not IP Address\n"); return SNMP_ERR_WRONGTYPE; } if ((*((int *) var_val)) < 0) { snmp_log(LOG_ERR, "invalid media net address"); return SNMP_ERR_WRONGVALUE; } if (var_val_len > sizeof(DWORD)) { snmp_log(LOG_ERR, "bad length\n"); return SNMP_ERR_WRONGLENGTH; } break; case IPMEDIATYPE: if (var_val_type != ASN_INTEGER) { snmp_log(LOG_ERR, "not integer\n"); return SNMP_ERR_WRONGTYPE; } if ((*((int *) var_val)) < 1 || (*((int *) var_val)) > 4) { snmp_log(LOG_ERR, "invalid media type"); return SNMP_ERR_WRONGVALUE; } if (var_val_len > sizeof(int)) { snmp_log(LOG_ERR, "bad length\n"); return SNMP_ERR_WRONGLENGTH; } break; case IPMEDIAPHYSADDRESS: if (var_val_type != ASN_OCTET_STR) { snmp_log(LOG_ERR, "not octet str"); return SNMP_ERR_WRONGTYPE; } if (var_val_len != 6) { snmp_log(LOG_ERR, "not correct ipAddress length: %d", var_val_len); return SNMP_ERR_WRONGLENGTH; } break; default: DEBUGMSGTL(("snmpd", "unknown sub-id %d in write_rte\n", var + 1)); return SNMP_ERR_NOTWRITABLE; } break; case RESERVE2: /* * Save the old value, in case of UNDO */ if (oldarp_row == NULL) { oldarp_row = (PMIB_IPNETROW) malloc(sizeof(MIB_IPNETROW)); *oldarp_row = *arp_row; } break; case ACTION: /* Perform the SET action (if reversible) */ switch (var) { case IPMEDIAIFINDEX: temp_row = *arp_row; arp_row->dwIndex = *((int *) var_val); /* * In case of new entry, physical address is mandatory. * * SetIpNetEntry will be done in COMMIT case */ if (!create_flag) { if (SetIpNetEntry(arp_row) != NO_ERROR) { arp_row->dwIndex = temp_row.dwIndex; retval = SNMP_ERR_COMMITFAILED; } /* * Don't know yet, whether change in ifIndex creates new row or not */ /* * else{ */ /* * temp_row.dwType = 2; */ /* * if(SetIpNetEntry(&temp_row) != NO_ERROR) */ /* * retval = SNMP_ERR_COMMITFAILED; */ /* * } */ } break; case IPMEDIANETADDRESS: temp_row = *arp_row; arp_row->dwAddr = *((int *) var_val); if (!create_flag) { if (SetIpNetEntry(arp_row) != NO_ERROR) { arp_row->dwAddr = oldarp_row->dwAddr; retval = SNMP_ERR_COMMITFAILED; } else { temp_row.dwType = 2; if (SetIpNetEntry(&temp_row) != NO_ERROR) { snmp_log(LOG_ERR, "Failed in ACTION, while deleting old row \n"); retval = SNMP_ERR_COMMITFAILED; } } } break; case IPMEDIATYPE: arp_row->dwType = *((int *) var_val); if (!create_flag) { if (SetIpNetEntry(arp_row) != NO_ERROR) retval = SNMP_ERR_COMMITFAILED; } break; case IPMEDIAPHYSADDRESS: memcpy(arp_row->bPhysAddr, var_val, var_val_len); arp_row->dwPhysAddrLen = var_val_len; if (!create_flag) { if (SetIpNetEntry(arp_row) != NO_ERROR) retval = SNMP_ERR_COMMITFAILED; } break; default: DEBUGMSGTL(("snmpd", "unknown sub-id %d in write_arp\n", var + 1)); retval = SNMP_ERR_NOTWRITABLE; } return retval; case UNDO: /* * Reverse the SET action and free resources */ if (oldarp_row != NULL) { /* * UNDO the changes done for existing entry. */ if (!create_flag) { if ((status = SetIpNetEntry(oldarp_row)) != NO_ERROR) { snmp_log(LOG_ERR, "Error in case UNDO, status : %d\n", status); retval = SNMP_ERR_UNDOFAILED; } } if (oldarp_row->dwAddr != arp_row->dwAddr) { arp_row->dwType = 2; /*If row was added/created delete that row */ if ((status = SetIpNetEntry(arp_row)) != NO_ERROR) { snmp_log(LOG_ERR, "Error while deleting added row, status : %d\n", status); retval = SNMP_ERR_UNDOFAILED; } } free(oldarp_row); oldarp_row = NULL; free(arp_row); arp_row = NULL; return retval; } break; case COMMIT: /* * if new entry and physical address specified, create new entry */ if (create_flag) { if (arp_row->dwPhysAddrLen != 0) { if ((status = CreateIpNetEntry(arp_row)) != NO_ERROR) { snmp_log(LOG_ERR, "Inside COMMIT: CreateIpNetEntry failed, status %d\n", status); retval = SNMP_ERR_COMMITFAILED; } } else { /* * For new entry, physical address must be set. */ snmp_log(LOG_ERR, "Can't create new entry without physical address\n"); retval = SNMP_ERR_WRONGVALUE; } /* * unset the create_flag, so that CreateIpNetEntry called only once */ create_flag = 0; } case FREE: /* * Free any resources allocated */ free(oldarp_row); oldarp_row = NULL; free(arp_row); arp_row = NULL; break; } return retval; }
DWORD C_ArpTable::arpspoof_check_by_ip(IPAddr ip,PMIB_IPNETROW old_row) { char *str1; in_addr ip_in_addr; ip_in_addr.S_un.S_addr=ip; str1=inet_ntoa(ip_in_addr); printf("Checking %s for arp spoofing...\n",str1); ULONG MacAddr[3],MacAddr2[3],MacAddr3[3]; ULONG PhysAddrLen = 12,PhysAddrLen2=12,PhysAddrLen3=12; PMIB_IPNETROW x=C_ArpTable::find_by_ip(ip); if(!x || x->dwType!=3) return 0; //if no entry or static entry. C_ArpTable::del_by_ip(ip); if(SendARP(ip,0, MacAddr, &PhysAddrLen)!=0) PhysAddrLen=0; C_ArpTable::del_by_ip(ip); if(SendARP(ip,0, MacAddr2, &PhysAddrLen2)!=0) { if(PhysAddrLen==0) return 0; //cant sendarp two times, exit; PhysAddrLen2=0; } C_ArpTable::del_by_ip(ip); if(SendARP(ip,0, MacAddr3, &PhysAddrLen3)!=0) PhysAddrLen3=0; if( (PhysAddrLen>0 && (PhysAddrLen!=x->dwPhysAddrLen || memcmp(MacAddr,x->bPhysAddr,PhysAddrLen)!=0)) || (PhysAddrLen2>0 && (PhysAddrLen2!=x->dwPhysAddrLen || memcmp(MacAddr2,x->bPhysAddr,PhysAddrLen2)!=0)) || (PhysAddrLen3>0 && (PhysAddrLen3!=x->dwPhysAddrLen || memcmp(MacAddr3,x->bPhysAddr,PhysAddrLen3)!=0)) ) { if( ((PhysAddrLen==0 || PhysAddrLen2==0) || (PhysAddrLen==PhysAddrLen2 && memcmp(MacAddr,MacAddr2,PhysAddrLen2)==0)) && ((PhysAddrLen==0 || PhysAddrLen3==0) || (PhysAddrLen==PhysAddrLen3 && memcmp(MacAddr,MacAddr3,PhysAddrLen3)==0)) && ((PhysAddrLen2==0 || PhysAddrLen3==0) || (PhysAddrLen2==PhysAddrLen3 && memcmp(MacAddr2,MacAddr3,PhysAddrLen3)==0)) ) { if(PhysAddrLen!=0) memcpy(x->bPhysAddr,MacAddr,PhysAddrLen); else memcpy(x->bPhysAddr,MacAddr2,PhysAddrLen2); } if(old_row) { if( (PhysAddrLen!=0 && old_row->dwPhysAddrLen==PhysAddrLen && memcmp(MacAddr,old_row->bPhysAddr,PhysAddrLen)==0) || (PhysAddrLen2!=0 && old_row->dwPhysAddrLen==PhysAddrLen2 && memcmp(MacAddr2,old_row->bPhysAddr,PhysAddrLen2)==0) || (PhysAddrLen3!=0 && old_row->dwPhysAddrLen==PhysAddrLen3 && memcmp(MacAddr3,old_row->bPhysAddr,PhysAddrLen3)==0) ) { memcpy(x->bPhysAddr,old_row->bPhysAddr,old_row->dwPhysAddrLen); printf("use old address.\n"); } } else printf("Spoofed new address.\n"); x->dwType=4; C_ArpTable::del_by_ip(ip); if(CreateIpNetEntry(x)!=0) { C_ArpTable::del_by_ip(ip); CreateIpNetEntry(x); } printf("Arp spoof of %s detected. setting arp entry to static.\nfor delete static entry run \"arp -d %s\"\n\n",str1,str1); return 1; //spoofing detected! } printf("Spoofing not detected.\n\n"); CreateIpNetEntry(x); /// C_ArpTable::reload(); return 0; }