/** * \brief Initialise a new LMP channel to accept an incoming binding request * * \param lc Storage for channel state * \param buflen_words Size of incoming buffer, in words * \param endpoint Capability to remote LMP endpoint */ errval_t lmp_chan_accept(struct lmp_chan *lc, size_t buflen_words, struct capref endpoint) { errval_t err; lmp_chan_init(lc); lc->remote_cap = endpoint; /* allocate a cap slot for the new endpoint cap */ err = slot_alloc(&lc->local_cap); if (err_is_fail(err)) { return err_push(err, LIB_ERR_SLOT_ALLOC); } /* allocate a local endpoint */ err = lmp_endpoint_create_in_slot(buflen_words, lc->local_cap, &lc->endpoint); if (err_is_fail(err)) { slot_free(lc->local_cap); return err_push(err, LIB_ERR_ENDPOINT_CREATE); } /* mark connected */ lc->connstate = LMP_CONNECTED; return SYS_ERR_OK; }
static errval_t move_to_root(struct capref src, struct capref *dest) #endif { errval_t err; err = slot_alloc_root(dest); if (err_is_fail(err)) { return err_push(err, LIB_ERR_SLOT_ALLOC); } err = cap_copy(*dest, src); if (err_is_fail(err)) { return err_push(err, LIB_ERR_CAP_COPY); } err = cap_delete(src); if (err_is_fail(err)) { return err_push(err, LIB_ERR_WHILE_DELETING); } err = slot_free(src); if (err_is_fail(err)) { return err_push(err, LIB_ERR_WHILE_FREEING_SLOT); } return SYS_ERR_OK; }
static void bind_ump_service_request_cont(struct monitor_binding *domain_binding, uintptr_t service_id, con_id_t my_mon_id, struct capref frame, uint32_t channel_length_in, uint32_t channel_length_out, struct capref notify_cap, struct intermon_binding *binding, con_id_t your_mon_id) { errval_t err, err2; /* Proxy the request */ err = domain_binding->tx_vtbl. bind_ump_service_request(domain_binding, NOP_CONT, service_id, my_mon_id, frame, channel_length_in, channel_length_out, notify_cap); if (err_is_fail(err)) { if(err_no(err) == FLOUNDER_ERR_TX_BUSY) { struct bind_ump_service_request_state *me = malloc(sizeof(struct bind_ump_service_request_state)); struct monitor_state *ist = domain_binding->st; me->args.service_id = service_id; me->args.mon_id = my_mon_id; me->args.frame = frame; me->args.channel_length_in = channel_length_in; me->args.channel_length_out = channel_length_out; me->args.notify = notify_cap; me->binding = binding; me->your_mon_id = your_mon_id; me->elem.cont = bind_ump_service_request_handler; err = monitor_enqueue_send(domain_binding, &ist->queue, get_default_waitset(), &me->elem.queue); assert(err_is_ok(err)); return; } err2 = cap_delete(frame); if (err_is_fail(err2)) { USER_PANIC_ERR(err2, "Cap delete failed"); } err2 = slot_free(frame); if (err_is_fail(err2)) { USER_PANIC_ERR(err2, "Cap destroy default failed"); } err2 = remote_conn_free(my_mon_id); if (err_is_fail(err2)) { USER_PANIC_ERR(err2, "remote_conn_free failed"); } intermon_caprep_t nullcap = {0,0,0,0}; err2 = binding->tx_vtbl.bind_ump_reply(binding, NOP_CONT, your_mon_id, 0, err, nullcap); if (err_is_fail(err2)) { USER_PANIC_ERR(err2, "Sending bind_ump_reply1 failed"); } } }
/** * Free slots * * @param[in] slots The slots to free * @param[in] start The first slot to free * @param[in] num_slots The number of slots to free */ static void __free_slots(slot_t **slots, uint64_t start, uint64_t num_slots) { uint64_t i; for (i = start; i < start + num_slots; i++) { /* FIXME Free layout's private data */ slot_free(slots[i]); } }
int epFactoryRecyleTimeEvent(alarmEventNode * thisEvent) { TIMEEVENT_FACTORY_SINGLETON; if (!timeEventFactoryFlag) return -1; slot_free(&epTimeEventAlloc, thisEvent); return 0; }
void mem_slot_test() { as_mem_slot_t *s = slot_new(4); slot_alloc(s, 4); int a = slot_alloc(s, 5); slot_alloc(s, 3); slot_free(s, a, 5); slot_alloc(s, 6); slot_print(s); slot_destroy(s); }
/** * \brief Allocate some memory for malloc to use * * This function will keep trying with smaller and smaller frames till * it finds a set of frames that satisfy the requirement. retbytes can * be smaller than bytes if we were able to allocate a smaller memory * region than requested for. */ static void *morecore_alloc(size_t bytes, size_t *retbytes) { errval_t err; struct morecore_state *state = get_morecore_state(); void *buf = NULL; size_t mapped = 0; size_t step = bytes; while (mapped < bytes) { struct capref cap; err = slot_alloc(&cap); if (err_is_fail(err)) { USER_PANIC_ERR(err, "slot_alloc failed"); } void *mid_buf = NULL; err = vspace_mmu_aware_map(&state->mmu_state, cap, step, &mid_buf, &step); if (err_is_ok(err)) { if (buf == NULL) { buf = mid_buf; } mapped += step; } else { /* vspace_mmu_aware_map failed probably because we asked for a very large frame, will try asking for smaller one. */ if (err_no(err) == LIB_ERR_FRAME_CREATE_MS_CONSTRAINTS) { err = slot_free(cap); if (err_is_fail(err)) { debug_err(__FILE__, __func__, __LINE__, err, "slot_free failed"); return NULL; } if (step < BASE_PAGE_SIZE) { // Return whatever we have allocated until now break; } step /= 2; continue; } else { debug_err(__FILE__, __func__, __LINE__, err, "vspace_mmu_aware_map fail"); return NULL; } } } *retbytes = mapped; return buf; }
void find_cap__rx_handler(struct intermon_binding *b, intermon_caprep_t caprep, genvaddr_t st) { errval_t err, cleanup_err; struct intermon_state *inter_st = (struct intermon_state*)b->st; coreid_t from = inter_st->core_id; struct capability cap; caprep_to_capability(&caprep, &cap); struct capref capref; err = slot_alloc(&capref); if (err_is_fail(err)) { goto send_err; } err = monitor_copy_if_exists(&cap, capref); if (err_is_fail(err)) { goto free_slot; } cleanup_err = cap_delete(capref); if (err_is_fail(cleanup_err)) { USER_PANIC_ERR(err, "failed to delete temporary cap"); } free_slot: cleanup_err = slot_free(capref); if (err_is_fail(cleanup_err)) { USER_PANIC_ERR(err, "failed to free slot for temporary cap"); } send_err: cleanup_err = find_cap_result(from, err, st); if (err_is_fail(cleanup_err)) { USER_PANIC_ERR(err, "failed to send find_cap result"); } }
/** * \brief Initialise a new LMP channel and initiate a binding * * \param lc Storage for channel state * \param cont Continuation for bind completion/failure * \param qnode Storage for an event queue node (used for queuing bind request) * \param iref IREF to which to bind * \param buflen_words Size of incoming buffer, in number of words */ errval_t lmp_chan_bind(struct lmp_chan *lc, struct lmp_bind_continuation cont, struct event_queue_node *qnode, iref_t iref, size_t buflen_words) { errval_t err; lmp_chan_init(lc); /* store bind arguments */ lc->iref = iref; lc->buflen_words = buflen_words; lc->bind_continuation = cont; /* allocate a cap slot for the new endpoint cap */ err = slot_alloc(&lc->local_cap); if (err_is_fail(err)) { waitset_chanstate_destroy(&lc->send_waitset); return err_push(err, LIB_ERR_SLOT_ALLOC); } /* allocate a local endpoint */ err = lmp_endpoint_create_in_slot(buflen_words, lc->local_cap, &lc->endpoint); if (err_is_fail(err)) { slot_free(lc->local_cap); waitset_chanstate_destroy(&lc->send_waitset); return err_push(err, LIB_ERR_ENDPOINT_CREATE); } // wait for the ability to use the monitor binding lc->connstate = LMP_BIND_WAIT; struct monitor_binding *mb = lc->monitor_binding = get_monitor_binding(); event_mutex_enqueue_lock(&mb->mutex, qnode, MKCLOSURE(send_bind_cont, lc)); return SYS_ERR_OK; }
void retrieve_request__rx(struct intermon_binding *b, intermon_caprep_t caprep, genvaddr_t st) { errval_t err, err2; struct intermon_state *inter_st = (struct intermon_state*)b->st; struct retrieve_response_st *rst; err = calloce(1, sizeof(*rst), &rst); PANIC_IF_ERR(err, "allocating retrieve respones state"); rst->st = st; rst->from = inter_st->core_id; struct capability rawcap; caprep_to_capability(&caprep, &rawcap); struct capref cap; err = slot_alloc(&cap); GOTO_IF_ERR(err, respond_err); err = monitor_copy_if_exists(&rawcap, cap); GOTO_IF_ERR(err, free_slot); distcap_state_t state; err = dom_cnode_get_state(get_cap_domref(cap), &state); GOTO_IF_ERR(err, delete_cap); if (distcap_state_is_busy(state)) { err = MON_ERR_REMOTE_CAP_RETRY; goto delete_cap; } if (distcap_state_is_foreign(state)) { err = MON_ERR_CAP_FOREIGN; goto delete_cap; } uint8_t relations, remote_relations; err = monitor_cap_has_relations(cap, 0xFF, &relations); GOTO_IF_ERR(err, delete_cap); err = monitor_remote_relations(cap, 0, 0, &remote_relations); GOTO_IF_ERR(err, delete_cap); rst->relations = relations | remote_relations | RRELS_COPY_BIT; err = monitor_set_cap_owner(cap_root, get_cap_addr(cap), get_cap_valid_bits(cap), rst->from); delete_cap: err2 = cap_delete(cap); DEBUG_IF_ERR(err2, "while deleting temp cap for retrieve"); free_slot: err2 = slot_free(cap); DEBUG_IF_ERR(err2, "freeing temp cap slot for retrieve"); respond_err: retrieve_result__enq(err, rst); }
int main(int argc, char **argv) { /* command line options */ int c; /* function-local options */ int foreground = FALSE; char *pid_file = NULL; /* config file */ char *configFile = NULL; /* config file parsing temp strings */ char tmp[MAX_CONFIG_STRING_SIZE], *tmpstr; /* open a connection to the syslog daemon */ openlog("pptpd", LOG_PID, PPTP_FACILITY); syslog(LOG_ERR, "MGR: Config file not found!"); /* process command line options */ while (1) { int option_index = 0; #ifdef BCRELAY char *optstring = "b:c:de:fhil:o:p:s:t:T:vwC:Dk"; #else char *optstring = "c:de:fhil:o:p:s:t:T:vwC:Dk"; #endif static struct option long_options[] = { #ifdef BCRELAY {"bcrelay", 1, 0, 0}, #endif {"conf", 1, 0, 'c'}, {"debug", 0, 0, 'd'}, {"ppp", 1, 0, 'e'}, {"fg", 0, 0, 'f'}, {"help", 0, 0, 'h'}, {"noipparam", 0, 0, 'i'}, {"listen", 1, 0, 'l'}, {"option", 1, 0, 'o'}, {"pidfile", 1, 0, 'p'}, {"speed", 1, 0, 's'}, {"stimeout", 1, 0, 't'}, {"ptimeout", 1, 0, 'T'}, {"version", 0, 0, 'v'}, {"logwtmp", 0, 0, 'w'}, {"connections", 1, 0, 'C'}, {"delegate", 0, 0, 'D'}, {"keep", 0, 0, 'k'}, {0, 0, 0, 0} }; c = getopt_long(argc, argv, optstring, long_options, &option_index); if (c == -1) break; /* convert long options to short form */ if (c == 0) #ifdef BCRELAY c = "bcdefhilopstvwCDk"[option_index]; #else c = "cdefhilopstvwCDk"[option_index]; #endif switch (c) { #ifdef BCRELAY case 'b': /* --bcrelay */ if (bcrelay) free(bcrelay); bcrelay = strdup(optarg); break; #endif case 'l': /* --listen */ tmpstr = lookup(optarg); if (!tmpstr) { syslog(LOG_ERR, "MGR: Invalid listening address: %s!", optarg); return 1; } if (bindaddr) free(bindaddr); bindaddr = strdup(tmpstr); break; case 'h': /* --help */ showusage(argv[0]); return 0; case 'i': /* --noipparam */ pptp_noipparam = TRUE; break; case 'e': /* --ppp */ if (ppp_binary) free(ppp_binary); ppp_binary = strdup(optarg); break; case 'd': /* --debug */ pptp_debug = TRUE; break; case 'f': /* --fg */ foreground = TRUE; break; case 'v': /* --version */ showversion(); return 0; case 'w': /* --logwtmp */ pptp_logwtmp = TRUE; break; case 'C': /* --connections */ pptp_connections = atoi(optarg); break; case 'D': /* --delegate */ pptp_delegate = TRUE; break; case 'o': /* --option */ if (pppdoptstr) free(pppdoptstr); pppdoptstr = strdup(optarg); break; case 'p': /* --pidfile */ if (pid_file) free(pid_file); pid_file = strdup(optarg); break; case 's': /* --speed */ if (speedstr) free(speedstr); speedstr = strdup(optarg); break; case 't': /* --stimeout */ pptp_stimeout = atoi(optarg); break; case 'T': /* --stimeout */ pptp_ptimeout = atoi(optarg); break; case 'k': /* --keep */ keep_connections = 1; break; case 'c': /* --conf */ { FILE *f; if (!(f = fopen(optarg, "r"))) { syslog(LOG_ERR, "MGR: Config file not found!"); return 1; } fclose(f); if(configFile) free(configFile); configFile = strdup(optarg); break; } default: showusage(argv[0]); return 1; } } /* Now that we have all the command line args.. lets open the * conf file and add anything else (remembering not to override * anything since the command line has more privilages :-) */ if (!configFile) configFile = strdup(PPTPD_CONFIG_FILE_DEFAULT); if (read_config_file(configFile, CONNECTIONS_KEYWORD, tmp) > 0) { pptp_connections = atoi(tmp); if (pptp_connections <= 0) pptp_connections = CONNECTIONS_DEFAULT; } slot_init(pptp_connections); if (!pptp_debug && read_config_file(configFile, DEBUG_KEYWORD, tmp) > 0) pptp_debug = TRUE; #ifdef BCRELAY if (!bcrelay && read_config_file(configFile, BCRELAY_KEYWORD, tmp) > 0) bcrelay = strdup(tmp); #endif if (!pptp_stimeout && read_config_file(configFile, STIMEOUT_KEYWORD, tmp) > 0) { pptp_stimeout = atoi(tmp); if (pptp_stimeout <= 0) pptp_stimeout = STIMEOUT_DEFAULT; } if (!pptp_ptimeout && read_config_file(configFile, PTIMEOUT_KEYWORD, tmp) > 0) { pptp_ptimeout = atoi(tmp); if (pptp_ptimeout <= 0) pptp_ptimeout = PTIMEOUT_DEFAULT; } if (!pptp_noipparam && read_config_file(configFile, NOIPPARAM_KEYWORD, tmp) > 0) { pptp_noipparam = TRUE; } if (!bindaddr && read_config_file(configFile, LISTEN_KEYWORD, tmp) > 0) { tmpstr = lookup(tmp); if(!tmpstr) { syslog(LOG_ERR, "MGR: Invalid listening address: %s!", tmp); return 1; } bindaddr = strdup(tmpstr); } if (!speedstr && read_config_file(configFile, SPEED_KEYWORD, tmp) > 0) speedstr = strdup(tmp); if (!pppdoptstr && read_config_file(configFile, PPPD_OPTION_KEYWORD, tmp) > 0) { pppdoptstr = strdup(tmp); } if (!ppp_binary && read_config_file(configFile, PPP_BINARY_KEYWORD, tmp) > 0) { ppp_binary = strdup(tmp); } if (!pptp_logwtmp && read_config_file(configFile, LOGWTMP_KEYWORD, tmp) > 0) { pptp_logwtmp = TRUE; } if (!pptp_delegate && read_config_file(configFile, DELEGATE_KEYWORD, tmp) > 0) { pptp_delegate = TRUE; } if (read_config_file(configFile, KEEP_KEYWORD, tmp) > 0) { keep_connections = TRUE; } if (!pid_file) pid_file = strdup((read_config_file(configFile, PIDFILE_KEYWORD, tmp) > 0) ? tmp : PIDFILE_DEFAULT); if (!pptp_delegate) { /* NOTE: remote then local, reason can be seen at the end of processIPStr */ /* grab the remoteip string from the config file */ if (read_config_file(configFile, REMOTEIP_KEYWORD, tmp) <= 0) { /* use "smart" defaults */ strlcpy(tmp, DEFAULT_REMOTE_IP_LIST, sizeof(tmp)); } processIPStr(REMOTE, tmp); /* grab the localip string from the config file */ if (read_config_file(configFile, LOCALIP_KEYWORD, tmp) <= 0) { /* use "smart" defaults */ strlcpy(tmp, DEFAULT_LOCAL_IP_LIST, sizeof(tmp)); } processIPStr(LOCAL, tmp); } free(configFile); /* if not yet set, adopt default PPP binary path */ if (!ppp_binary) ppp_binary = strdup(PPP_BINARY); /* check that the PPP binary is executable */ if (access(ppp_binary, X_OK) < 0) { syslog(LOG_ERR, "MGR: PPP binary %s not executable", ppp_binary); return 1; } /* check that the PPP options file is readable */ if (pppdoptstr && access(pppdoptstr, R_OK) < 0) { syslog(LOG_ERR, "MGR: PPP options file %s not readable", pppdoptstr); return 1; } #ifdef BCRELAY /* check that the bcrelay binary is executable */ if (bcrelay && access(BCRELAY_BIN, X_OK) < 0) { syslog(LOG_ERR, "MGR: bcrelay binary %s not executable", BCRELAY_BIN); return 1; } #endif syslog(LOG_INFO, "accel-pptpd-%s compiled for pppd-%s\n",VERSION, "2.4.2"); if (!foreground) { #if HAVE_DAEMON closelog(); freopen("/dev/null", "r", stdin); daemon(0, 0); /* returns to child only */ /* pid will have changed */ openlog("pptpd", LOG_PID, PPTP_FACILITY); #else /* !HAVE_DAEMON */ my_daemon(argc, argv); /* returns to child if !HAVE_FORK * never returns if HAVE_FORK (re-execs with -f) */ #endif } #ifdef BCRELAY if (bcrelay) { syslog(LOG_DEBUG, "CTRL: BCrelay incoming interface is %s", bcrelay); /* Launch BCrelay */ #ifndef HAVE_FORK switch(bcrelayfork = vfork()){ #else switch(bcrelayfork = fork()){ #endif case -1: /* fork() error */ syslog(LOG_ERR, "CTRL: Error forking to exec bcrelay"); _exit(1); case 0: /* child */ syslog(LOG_DEBUG, "CTRL (BCrelay Launcher): Launching BCrelay with pid %i", bcrelayfork); launch_bcrelay(); syslog(LOG_ERR, "CTRL (BCrelay Launcher): Failed to launch BCrelay."); _exit(1); } } /* End bcrelay */ #endif #ifdef CONFIG_NETtel /* turn the NETtel VPN LED on */ ledman_cmd(LEDMAN_CMD_ON, LEDMAN_VPN); #endif /* after we have our final pid... */ log_pid(pid_file); /* manage connections until SIGTERM */ pptp_manager(argc, argv); #ifdef BCRELAY if (bcrelayfork > 0) { syslog(LOG_DEBUG, "CTRL: Closing child BCrelay with pid %i", bcrelayfork); kill(bcrelayfork, SIGTERM); } #endif slot_free(); return 0; } static void log_pid(char *pid_file) { FILE *f; pid_t pid; pid = getpid(); if ((f = fopen(pid_file, "w")) == NULL) { syslog(LOG_ERR, "PPTPD: failed to open(%s), errno=%d\n", pid_file, errno); return; } fprintf(f, "%d\n", pid); fclose(f); }