int ip_selector_db_lookup( struct IPSelectorDb *db, int part, const struct IPSelectorFields *fields) { struct IPSelectorDbEntry *entry = db->heads[part]; int action = -1; DEBUG_LOW( lookup, "Fields %p: Lookup db part %d: %s", fields, part, debug_str_ip_selector_fields( DEBUG_STRBUF_GET(), fields, sizeof *fields)); if (entry == NULL) { DEBUG_LOW( lookup, "Fields %p: Lookup db part %d: no entries; no match", fields, part); } while (entry != NULL) { struct IPSelectorGroup *selector_group = (void *)(entry + 1); if (ip_selector_match_fields_to_group(selector_group, fields)) { action = entry->action; DEBUG_LOW(lookup, "Fields %p matched entry %p.", fields, entry); break; } entry = entry->next; } DEBUG_LOW(lookup, "Fields %p action is %d.", fields, action); return action; }
void Debug_Output(U8 bCnt) { DEBUG_HIGH(); while(bCnt--) { DEBUG_LOW(); DelayUs2x(1); DEBUG_HIGH(); } }
static ssize_t spd_proc_write( struct file *file, const char __user *data, size_t data_len, loff_t *pos) { size_t bytes_read = 0; DEBUG_LOW(proc, "Write of %d bytes.", (int) data_len); while (bytes_read < data_len) { struct KernelSpdCommand command; int status; if (data_len < sizeof command) { DEBUG_FAIL( proc, "Data length %d less than sizeof command %d bytes.", (int) data_len, (int) sizeof command); bytes_read = -EFAULT; break; } status = copy_from_user(&command, data, sizeof command); if (status != 0) { DEBUG_FAIL(proc, "Copy from user failed."); bytes_read = -EFAULT; break; } if (command.bytecount < sizeof command) { DEBUG_FAIL( proc, "Command bytecount %d less than command size %d.", (int) command.bytecount, (int) sizeof command); bytes_read = -EINVAL; break; } if (command.bytecount > KERNELSPD_PROCFS_COMMAND_BYTECOUNT_MAX) { DEBUG_FAIL( proc, "Command bytecount %d bigger than max command size %d.", (int) command.bytecount, (int) KERNELSPD_PROCFS_COMMAND_BYTECOUNT_MAX); bytes_read = -EINVAL; break; } if (command.bytecount > data_len - bytes_read) { DEBUG_FAIL( proc, "Command bytecount %d bigger than data_len %d.", (int) command.bytecount, (int) data_len); bytes_read = -EINVAL; break; } bytes_read += sizeof command; status = process_command( &command, data + bytes_read, command.bytecount - sizeof command); if (status < 0) { bytes_read = status; break; } bytes_read += command.bytecount; } return bytes_read; }
int process_command( struct KernelSpdCommand *cmd, const char __user *cmd_data, size_t cmd_data_bytecount) { int status = 0; DEBUG_LOW(proc, "Processing command id %d.", cmd->command_id); switch (cmd->command_id) { case KERNEL_SPD_ACTIVATE: { int ipsec_boundary_bytecount = cmd_data_bytecount; if (active != 0) { DEBUG_FAIL(def, "Kernel SPD already active."); status = -EFAULT; } else { status = update_ipsec_boundary( cmd_data, ipsec_boundary_bytecount); if (status != 0) { break; } if (spd_hooks_init() != 0) { DEBUG_FAIL(proc, "Kernel SPD Failed activating NF Hooks."); status = -EFAULT; } active = 1; DEBUG_HIGH( kernel, "Kernel SPD activated. IPsec boundary: '%s'.", ipsec_boundary); } } break; case KERNEL_SPD_DEACTIVATE: { if (active == 0) { DEBUG_FAIL(proc, "Kernel SPD not active."); } else { DEBUG_HIGH(proc, "Kernel SPD deactivated."); spd_hooks_uninit(); bypass_kuid = INVALID_UID; } active = 0; } break; case KERNEL_SPD_INSERT_ENTRY: { struct IPSelectorDbEntry *entry; const int payload_bytecount = cmd_data_bytecount; if (!KERNEL_SPD_ID_VALID(cmd->spd_id)) { DEBUG_FAIL( proc, "Invalid SPD id %d.", cmd->spd_id); status = -EFAULT; break; } entry = vmalloc(sizeof *entry + payload_bytecount); if (entry == NULL) { DEBUG_FAIL( proc, "vmalloc(%d) failed.", (int) (sizeof *entry + payload_bytecount)); status = -EFAULT; break; } status = copy_from_user(entry + 1, cmd_data, payload_bytecount); if (status != 0) { DEBUG_FAIL(proc, "Copy from user failed."); vfree(entry); status = -EFAULT; break; } entry->action = cmd->action_id; entry->id = cmd->entry_id; entry->priority = cmd->priority; if (ip_selector_db_entry_check( entry, sizeof *entry + payload_bytecount) < 0) { DEBUG_FAIL(proc, "Selector check failed."); vfree(entry); status = -EFAULT; break; } DEBUG_DUMP( proc, debug_dump_ip_selector_group, entry + 1, payload_bytecount, "Insert entry %d to spd " "id %d action %d priority %d precedence %d:", entry->id, cmd->spd_id, entry->action, entry->priority, cmd->precedence); write_lock_bh(&spd_lock); ip_selector_db_entry_add( &spd, cmd->spd_id, entry, cmd->precedence); write_unlock_bh(&spd_lock); } break; case KERNEL_SPD_REMOVE_ENTRY: if (!KERNEL_SPD_ID_VALID(cmd->spd_id)) { DEBUG_FAIL( proc, "Invalid SPD id %d.", cmd->spd_id); status = -EFAULT; break; } { struct IPSelectorDbEntry *removed; write_lock_bh(&spd_lock); removed = ip_selector_db_entry_remove( &spd, cmd->spd_id, cmd->entry_id); write_unlock_bh(&spd_lock); if (removed != NULL) { DEBUG_DUMP( proc, debug_dump_ip_selector_group, removed + 1, -1, "Removed entry %d to spd id %d action %d " "priority %d:", removed->id, cmd->spd_id, removed->action, removed->priority); vfree(removed); } else { DEBUG_FAIL( proc, "Remove failed: Entry %d not found from spd id %d.", cmd->entry_id, cmd->spd_id); } } break; case KERNEL_SPD_UPDATE_IPSEC_BOUNDARY: { int new_ipsec_boundary_bytecount = cmd_data_bytecount; if (active == 0) { DEBUG_FAIL(def, "Kernel SPD is not active."); return -EFAULT; } status = update_ipsec_boundary( cmd_data, new_ipsec_boundary_bytecount); if (status != 0) { break; } DEBUG_HIGH( kernel, "IPsec boundary updated: '%s'.", ipsec_boundary); } break; case KERNEL_SPD_VERSION_SYNC: { int version_bytecount = cmd_data_bytecount; uint32_t version; if (version_bytecount != sizeof version) { DEBUG_FAIL( def, "Invalid version size %d; should be %d.", version_bytecount, (int) sizeof version); return -EFAULT; } status = copy_from_user( &version, cmd_data, sizeof version); if (status != 0) { DEBUG_FAIL(def, "Copy from user failed."); return -EFAULT; } if (version != KERNEL_SPD_VERSION) { DEBUG_FAIL( def, "Invalid version %d; should be %d.", version, KERNEL_SPD_VERSION); return -EINVAL; } DEBUG_HIGH( kernel, "Versions in sync: %d.", version); } break; case KERNEL_SPD_ADD_BYPASS_UID: { uint32_t uid; if (active == 0) { DEBUG_FAIL(def, "Kernel SPD is not active."); return -EFAULT; } status = copy_from_user( &uid, cmd_data, sizeof uid); if (status != 0) { DEBUG_FAIL(def, "Copy from user failed."); return -EFAULT; } write_lock_bh(&spd_lock); bypass_kuid = make_kuid(current_user_ns(), (uid_t) uid); write_unlock_bh(&spd_lock); DEBUG_HIGH( kernel, "Set bypass uid to %u.", uid); } break; default: DEBUG_FAIL(proc, "Unknown command id %d.", cmd->command_id); break; } DEBUG_LOW(proc, "Returning %d", status); return status; }