int main(int argc, char *argv[]) { parse_arg_list(argc, argv); open_logfile(NULL); report_info("main()", "About Server:\nName: %s\nPID: %d\nAddress: %s\nPort: %d", server_name, getpid(), inet_ntoa(*(struct in_addr *)&server_address), server_port); start_server(); return 0; }
int userfw_cmd_dispatch(unsigned char *buf, struct socket *so, struct thread *td) { int err = 0; userfw_module_id_t dst = 0; struct userfw_io_header *msg = (struct userfw_io_header *)buf; const userfw_modinfo *modinfo = NULL; const userfw_cmd_descr *cmdinfo = NULL; struct userfw_io_header *cmd, *opcode, *cookie = NULL, *mod_id; userfw_arg *parsed_args = NULL; int i, cookie_val; userfw_cmd_access_check access_checker = NULL; if (msg->type != T_CONTAINER || (msg->subtype != ST_MESSAGE && msg->subtype != ST_CMDCALL)) return EOPNOTSUPP; if (msg->length < sizeof(*msg) + sizeof(*cmd)) return EINVAL; if (msg->subtype == ST_CMDCALL) cmd = msg; else { cmd = userfw_io_find_block(buf + sizeof(*msg), msg->length - sizeof(*msg), T_CONTAINER, ST_CMDCALL); cookie = userfw_io_find_block(buf + sizeof(*msg), msg->length - sizeof(*msg), T_UINT32, ST_COOKIE); } if (cmd == NULL || (cmd != msg && !BLOCK_FITS_INTO_OUTER(cmd, msg))) return EINVAL; if (cookie != NULL && (!BLOCK_FITS_INTO_OUTER(cookie, msg) || cookie->length != sizeof(*cookie) + sizeof(uint32_t))) return EINVAL; mod_id = userfw_io_find_block((char*)cmd + sizeof(*cmd), cmd->length - sizeof(*cmd), T_UINT32, ST_MOD_ID); if (mod_id == NULL || ! BLOCK_FITS_INTO_OUTER(mod_id, cmd) || mod_id->length != sizeof(*mod_id) + sizeof(uint32_t)) return EINVAL; dst = *((uint32_t*)((char*)mod_id + sizeof(*mod_id))); modinfo = userfw_mod_find(dst); if (modinfo == NULL) return ECONNREFUSED; opcode = userfw_io_find_block((char*)cmd + sizeof(*cmd), cmd->length - sizeof(*cmd), T_UINT32, ST_OPCODE); if (opcode == NULL || ! BLOCK_FITS_INTO_OUTER(opcode, cmd) || opcode->length != sizeof(*opcode) + sizeof(uint32_t)) return EINVAL; cmdinfo = userfw_mod_find_cmd(dst, *((uint32_t*)((char*)opcode + sizeof(*opcode)))); if (cmdinfo == NULL) return EINVAL; parsed_args = malloc(sizeof(userfw_arg)*(cmdinfo->nargs), M_USERFW, M_WAITOK | M_ZERO); err = parse_arg_list((unsigned char *)cmd + sizeof(*cmd), cmd->length - sizeof(*cmd), parsed_args, cmdinfo->nargs, cmdinfo->arg_types); access_checker = cmdinfo->is_allowed; if (access_checker == NULL) access_checker = userfw_cmd_access_only_root; if (err == 0) err = (*access_checker)(dst, cmdinfo, parsed_args, so, td) ? 0 : EPERM; cookie_val = cookie != NULL ? (*((uint32_t*)((char*)cookie + sizeof(*cookie)))) : 0; if (err != 0) userfw_msg_reply_error(so, cookie_val, err); if (err == 0) err = cmdinfo->do_cmd(*((uint32_t*)((char*)opcode + sizeof(*opcode))), cookie_val, parsed_args, so, td); for(i = 0; i < cmdinfo->nargs; i++) { if (parsed_args[i].type != T_INVAL) free_arg(&(parsed_args[i]), M_USERFW); } free(parsed_args, M_USERFW); return 0; }
int parse_arg(unsigned char *buf, userfw_arg *dst) { struct userfw_io_header *arg = (struct userfw_io_header *)buf; unsigned char *data = buf + sizeof(*arg); dst->type = arg->type; switch (arg->type) { case T_STRING: case T_HEXSTRING: dst->string.length = arg->length - sizeof(*arg); dst->string.data = malloc(arg->length - sizeof(*arg), M_USERFW, M_WAITOK); bcopy(buf + sizeof(*arg), dst->string.data, arg->length - sizeof(*arg)); break; case T_UINT16: bcopy(data, &(dst->uint16.value), sizeof(uint16_t)); break; case T_UINT32: bcopy(data, &(dst->uint32.value), sizeof(uint32_t)); break; case T_UINT64: bcopy(data, &(dst->uint64.value), sizeof(uint64_t)); break; case T_IPv4: bcopy(data, &(dst->ipv4.addr), sizeof(uint32_t)); bcopy(data + sizeof(uint32_t), &(dst->ipv4.mask), sizeof(uint32_t)); break; case T_IPv6: bcopy(data, &(dst->ipv6.addr), 4*sizeof(uint32_t)); bcopy(data + 4*sizeof(uint32_t), &(dst->ipv6.addr), 4*sizeof(uint32_t)); break; case T_MATCH: case T_ACTION: { userfw_match *match = NULL; userfw_action *action = NULL; struct userfw_io_header *opcode_p, *mod_id_p; const userfw_match_descr *matchdescr = NULL; const userfw_action_descr *actiondescr = NULL; opcode_t opcode; userfw_module_id_t mod_id; int err = 0; if (arg->length < sizeof(*arg) + sizeof(*opcode_p) + sizeof(*mod_id_p)) return EINVAL; opcode_p = userfw_io_find_block(data, arg->length - sizeof(*arg), T_UINT32, ST_OPCODE); if (opcode_p == NULL || ! BLOCK_FITS_INTO_OUTER(opcode_p, arg) || opcode_p->length != sizeof(*opcode_p) + sizeof(uint32_t)) return EINVAL; opcode = *((uint32_t*)((char*)opcode_p + sizeof(*opcode_p))); mod_id_p = userfw_io_find_block(data, arg->length - sizeof(*arg), T_UINT32, ST_MOD_ID); if (mod_id_p == NULL || ! BLOCK_FITS_INTO_OUTER(mod_id_p, arg) || mod_id_p->length != sizeof(*mod_id_p) + sizeof(uint32_t)) return EINVAL; mod_id = *((uint32_t*)((char*)mod_id_p + sizeof(*mod_id_p))); switch(arg->type) { case T_MATCH: matchdescr = userfw_mod_find_match(mod_id, opcode); if (matchdescr == NULL) return EHOSTUNREACH; if (userfw_mod_inc_refcount(mod_id) == 0) { match = malloc(sizeof(userfw_match), M_USERFW, M_WAITOK | M_ZERO); match->mod = mod_id; match->op = opcode; match->nargs = matchdescr->nargs; match->do_match = matchdescr->do_match; match->dtor = matchdescr->dtor; err = parse_arg_list(data, arg->length - sizeof(*arg), match->args, match->nargs, matchdescr->arg_types); if (err == 0 && matchdescr->ctor != NULL) err = matchdescr->ctor(match); dst->match.p = match; } else { err = EHOSTUNREACH; dst->type = T_INVAL; } break; case T_ACTION: actiondescr = userfw_mod_find_action(mod_id, opcode); if (actiondescr == NULL) return EHOSTUNREACH; if (userfw_mod_inc_refcount(mod_id) == 0) { action = malloc(sizeof(userfw_action), M_USERFW, M_WAITOK | M_ZERO); action->mod = mod_id; action->op = opcode; action->nargs = actiondescr->nargs; action->do_action = actiondescr->do_action; action->dtor = actiondescr->dtor; err = parse_arg_list(data, arg->length - sizeof(*arg), action->args, action->nargs, actiondescr->arg_types); if (err == 0 && actiondescr->ctor != NULL) err = actiondescr->ctor(action); dst->action.p = action; } else { err = EHOSTUNREACH; dst->type = T_INVAL; } break; } if (err != 0) return err; } break; default: dst->type = T_INVAL; return EINVAL; } return 0; }