Beispiel #1
0
/**
 * \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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
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");
        }
    }
}
Beispiel #4
0
/**
 * 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]);
    }
}
Beispiel #5
0
int epFactoryRecyleTimeEvent(alarmEventNode * thisEvent)
{
    TIMEEVENT_FACTORY_SINGLETON;

    if (!timeEventFactoryFlag)
        return -1;

    slot_free(&epTimeEventAlloc, thisEvent);
    return 0;
}
Beispiel #6
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);
}
Beispiel #7
0
/**
 * \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;
}
Beispiel #8
0
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");
    }
}
Beispiel #9
0
/**
 * \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;
}
Beispiel #10
0
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);
}
Beispiel #11
0
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);
}