Пример #1
0
/*
 * 0001/0002 (client->server) Client Online
 *
 * Although the client will probably make more requests to learn about its
 * environment after this, reception of the Client Online message is when the
 * server will consider the client to be online, and, in the case of a BOS
 * connection, light them up on the buddy lists.
 */
static int
toscar_snachandler_0001_0002(struct nafmodule *mod, struct nafconn *conn, struct toscar_snac *snac)
{
	char *sn = NULL;
	struct gnrnode *node;

	if (!(conn->type & NAF_CONN_TYPE_CLIENT))
		return HRET_ERROR;

	if ((naf_conn_tag_fetch(mod, conn->endpoint, "conn.screenname", NULL, (void **)&sn) == -1) || !sn) {
		if (timps_oscar__debug > 0)
			dvprintf(mod, "[cid %lu] received Client Online on connection with no user info; killing\n", conn->cid);
		return HRET_ERROR;
	}

	{
		/*
		 * Disconnect any old server connections for this user. AIM
		 * used to do this automatically, but they fixed the glitch.
		 */
		toscar__detacholdconns(mod, sn);
	}

	node = gnr_node_online(mod, sn, OSCARSERVICE,
				GNR_NODE_FLAG_NONE, GNR_NODE_METRIC_LOCAL);
	if (!node) {
		if (timps_oscar__debug > 0)
			dvprintf(mod, "[cid %lu] [%s] unable to create gnrnode; disconnecting\n", conn->cid, sn);
		return HRET_ERROR;
	}

	return HRET_FORWARD;
}
Пример #2
0
static int
toscar_flap_handlechan1__newconn(struct nafmodule *mod, struct nafconn *conn, naf_tlv_t **tlvh)
{
	naf_tlv_t *cktlv;
	char *ip = NULL, *sn = NULL;
	naf_u16_t servtype = TOSCAR_SERVTYPE_UNKNOWN;
	int ret = HRET_DIGESTED;

	if (!(cktlv = naf_tlv_get(mod, *tlvh, 0x0006))) {
		/* no cookie = wtf are we doing here? */
		if (timps_oscar__debug > 0)
			dvprintf(mod, "[cid %lu] cookie FLAP missing cookie\n", conn->cid);
		return HRET_ERROR;
	}

	if (toscar_ckcache_rem(mod, cktlv->tlv_value, cktlv->tlv_length,
				&ip, &sn, &servtype) == -1) {
		if (timps_oscar__debug > 0)
			dvprintf(mod, "[cid %lu] received unknown cookie\n", conn->cid);
		ret = HRET_ERROR;
		goto out;
	}

	if (timps_oscar__debug > 1)
		dvprintf(mod, "[cid %lu] matched cookie to sn '%s', ip '%s', servtype %d\n", conn->cid, sn, ip, servtype);

	if (naf_conn_startconnect(mod, conn, ip, TIMPS_OSCAR_DEFAULTPORT) == -1) {
		ret = HRET_ERROR;
		goto out;
	}

	conn->servtype = servtype;
	conn->endpoint->servtype = servtype;

	if (sn) {
		/* XXX store full userinfo here */
		/* Note that the user information is attached to the server connection. */
		if (naf_conn_tag_add(mod, conn->endpoint, "conn.screenname", 'S', sn) == -1) {
			ret = HRET_ERROR;
			goto out;
		}
		sn = NULL;
	}

	/* need to resend these when connection completes */
	if (naf_conn_tag_add(mod, conn->endpoint, "conn.cookietlvs", 'V', (void *)*tlvh) == -1) {
		ret = HRET_ERROR;
		goto out;
	}
	*tlvh = NULL; /* will get freed with tag */

out:
	naf_free(mod, sn);
	naf_free(mod, ip);
	return ret;
}
Пример #3
0
/*! @brief Sets the process's parameter buffer.

    Sets the process's parameter buffer to the given RAM dataspace. Only support a RAM dataspace
    which orginated from the process server's own dataspace implementation, does not support
    an external dataspace.
*/
refos_err_t
proc_set_parambuffer_handler(void *rpc_userptr , seL4_CPtr rpc_dataspace , uint32_t rpc_size)
{
    struct proc_pcb *pcb = (struct proc_pcb*) rpc_userptr;
    struct procserv_msg *m = (struct procserv_msg*) pcb->rpcClient.userptr;
    assert(pcb->magic == REFOS_PCB_MAGIC);
    struct ram_dspace *dataspace;

    /* Special case zero size and NULL parameter buffer - means unset the parameter buffer. */
    if (rpc_size == 0 && rpc_dataspace == 0) {
        proc_set_parambuffer(pcb, NULL);
        return ESUCCESS;
    }

    if (!check_dispatch_caps(m, 0x00000001, 1)) {
        return EINVALIDPARAM;
    }

    /* Check if the given badge is a RAM dataspace. */
    if (!dispatcher_badge_dspace(rpc_dataspace)) {
        return EINVALIDPARAM;
    }

    /* Retrieve RAM dataspace structure. */
    dataspace = ram_dspace_get_badge(&procServ.dspaceList, rpc_dataspace);
    if (!dataspace) {
        dvprintf("No such dataspace!.\n");
        return EINVALID;
    }

    /* Set new parameter buffer. */
    proc_set_parambuffer(pcb, dataspace);
    return ESUCCESS;
}
Пример #4
0
/*! @brief Handles device server device map syscalls. */
refos_err_t
proc_device_map_handler(void *rpc_userptr , seL4_CPtr rpc_window , uint32_t rpc_windowOffset ,
        uint32_t rpc_paddr , uint32_t rpc_size , int rpc_cached)
{
    struct proc_pcb *pcb = (struct proc_pcb*) rpc_userptr;
    struct procserv_msg *m = (struct procserv_msg*) pcb->rpcClient.userptr;
    assert(pcb && pcb->magic == REFOS_PCB_MAGIC);

    if (!check_dispatch_caps(m, 0x00000001, 1)) {
        return EINVALIDPARAM;
    }

    if ((pcb->systemCapabilitiesMask & PROCESS_PERMISSION_DEVICE_MAP) == 0) {
        dvprintf("Process needs device map permissions to perform this.\n");
        return EACCESSDENIED;
    }

    /* Retrieve and verify window. */
    struct w_window *window = w_get_window(&procServ.windowList, rpc_window - W_BADGE_BASE);
    if (!window) {
        ROS_ERROR("window does not exist!\n");
        return EINVALIDWINDOW;
    }

    /* Get the client PCB that owns the given window. */
    struct proc_pcb* clientPCB = pid_get_pcb(&procServ.PIDList, window->clientOwnerPID);
    if (!clientPCB) {
        ROS_ERROR("invalid window owner!\n");
        return EINVALID;
    }
    assert(clientPCB->magic == REFOS_PCB_MAGIC);

    return vs_map_device(&clientPCB->vspace, window, rpc_windowOffset, rpc_paddr, rpc_size,
                         rpc_cached ? true : false);
}
Пример #5
0
static void
freetag(struct nafmodule *mod, void *object, const char *tagname, char tagtype, void *tagdata)
{

	dvprintf(mod, "freetag: unknown tagname '%s'\n", tagname);

	return;
}
Пример #6
0
void dprintf(const char *debug_context, const char *fmt, ...)
{
    va_list args;

    va_start(args, fmt);
    dvprintf(debug_context, fmt, args);
    va_end(args);
}
Пример #7
0
struct gnrnode *gnr_node_online(struct nafmodule *owner, const char *name, const char *service, naf_u32_t flags, int metric)
{
	struct gnrnode *gn;

	if (!owner || !name || !service)
		return NULL;

	if ((gn = gnr_node_findbyname(name, service)))
		return gn;

	if (!(gn = naf_malloc(gnr__module, sizeof(struct gnrnode))))
		return NULL;
	memset(gn, 0, sizeof(struct gnrnode));

	if (!(gn->name = naf_strdup(gnr__module, name))) {
		naf_free(gnr__module, gn);
		return NULL;
	}
	if (!(gn->service = naf_strdup(gnr__module, service))) {
		naf_free(gnr__module, gn->name);
		naf_free(gnr__module, gn);
		return NULL;
	}
	gn->flags = flags;
	gn->metric = metric;
	gn->ownermod = owner;
	gn->taglistv = NULL;
	gn->refcount = 0; /* caller should immediatly _ref if it wants it */
	gn->createtime = gn->lastuse = time(NULL);
	gn->ttl = -1;

	if (gn->metric > GNR_NODE_METRIC_LOCAL)
		gn->ttl = GNR_NODE_TTL_DEFAULT;

	gnr_node__hash_add(gn);

	gnr__nodestats.total++;
	if (gn->metric == GNR_NODE_METRIC_LOCAL)
		gnr__nodestats.local++;
	else if (gn->metric == GNR_NODE_METRIC_MAX)
		gnr__nodestats.external++;
	else
		gnr__nodestats.peered++;

#if 0
	dvprintf(gnr__module, "user online: %s[%s][%s][%s%s%s]\n",
			gn->name,
			gn->service,
			gn->ownermod ? gn->ownermod->name : "unknown",
			(gn->metric == GNR_NODE_METRIC_LOCAL) ? "local" : "",
			GNR_NODE_METRIC_ISPEERED(gn->metric) ? "peer" : "",
			(gn->metric == GNR_NODE_METRIC_MAX) ? "remote" : "");
#endif

	gnr_event_throw_withnode(GNR_EVENT_NODEUP, gn, NULL);

	return gn;
}
Пример #8
0
/*! \brief Call from external dataserver asking to be the content initialiser for this dataspace. */
refos_err_t
data_have_data_handler(void *rpc_userptr , seL4_CPtr rpc_dspace_fd , seL4_CPtr rpc_faultNotifyEP ,
                       uint32_t* rpc_dataID)
{
    struct proc_pcb *pcb = (struct proc_pcb*) rpc_userptr;
    struct procserv_msg *m = (struct procserv_msg*) pcb->rpcClient.userptr;
    assert(pcb && pcb->magic == REFOS_PCB_MAGIC);

    if (!(check_dispatch_caps(m, 0x00000001, 2) || check_dispatch_caps(m, 0x00000001, 1))) {
        return EINVALIDPARAM;
    }

    if (rpc_dataID) {
        (*rpc_dataID) = 0;
    }

    /* Verify and find the RAM dataspace. */
    if (!dispatcher_badge_dspace(rpc_dspace_fd)) {
        ROS_ERROR("EINVALIDPARAM: invalid RAM dataspace badge..\n");
        return EINVALIDPARAM;
    }
    struct ram_dspace *dspace = ram_dspace_get_badge(&procServ.dspaceList, rpc_dspace_fd);
    if (!dspace) {
        ROS_ERROR("EINVALIDPARAM: dataspace not found.\n");
        return EINVALIDPARAM;
    }

    /* Special case - no fault notify EP, means unset content-init mode. */
    if (!rpc_faultNotifyEP) {
        cspacepath_t path;
        vka_cspace_make_path(&procServ.vka, 0, &path);
        return ram_dspace_content_init(dspace, path, PID_NULL);
    }

    /* Copyout the content-init fault notify EP. */
    seL4_CPtr faultNotifyEP = dispatcher_copyout_cptr(rpc_faultNotifyEP);
    if (!faultNotifyEP) {
        dvprintf("could not copy out faultNotifyEP.");
        return EINVALIDPARAM; 
    }
    cspacepath_t path;
    vka_cspace_make_path(&procServ.vka, faultNotifyEP, &path);

    /* Initialise the dataspace content with given dataserver EP. */
    int error = ram_dspace_content_init(dspace, path, pcb->pid);
    if (error != ESUCCESS) {
        dispatcher_release_copyout_cptr(faultNotifyEP);
        return error;
    }

    if (rpc_dataID) {
        (*rpc_dataID) = dspace->ID;
    }
    return ESUCCESS;
}
Пример #9
0
/*
 * 0001/000b (server->client) Server Pause
 *
 * This is the first step in migration, where the server moves the client to a
 * different server.
 *
 */
static int
toscar_snachandler_0001_000b(struct nafmodule *mod, struct nafconn *conn, struct toscar_snac *snac)
{
	char *sn = NULL;

	naf_conn_tag_fetch(mod, conn, "conn.screenname", NULL, (void **)&sn);

	dvprintf(mod, "[cid %lu] [%s] received server pause; disconnecting for safety\n", conn->cid, sn);

	return HRET_ERROR;
}
Пример #10
0
/*
 * 0001/0003 (server->client) Host Online
 *
 * Received after we're somewhat authenticated with the host.
 *
 */
static int
toscar_snachandler_0001_0003(struct nafmodule *mod, struct nafconn *conn, struct toscar_snac *snac)
{

	conn->flags |= TOSCAR_FLAG_READY;

	if (timps_oscar__debug > 0)
		dvprintf(mod, "[%lu] received Host Online\n", conn->cid);

	return HRET_FORWARD;
}
Пример #11
0
/*! @brief Handles memory window resize syscalls. */
refos_err_t
proc_resize_mem_window_handler(void *rpc_userptr , seL4_CPtr rpc_window , uint32_t rpc_size)
{
    struct proc_pcb *pcb = (struct proc_pcb*) rpc_userptr;
    struct procserv_msg *m = (struct procserv_msg*) pcb->rpcClient.userptr;
    assert(pcb && pcb->magic == REFOS_PCB_MAGIC);

    if (!check_dispatch_caps(m, 0x00000001, 1)) {
        dvprintf("Warning: proc_resize_mem_window invalid window cap.\n");
        return EINVALIDWINDOW;
    }

    if (!dispatcher_badge_window(rpc_window)) {
        dvprintf("Warning: proc_resize_mem_window invalid window badge.\n");
        return EINVALIDWINDOW;
    }

    /* Perform the actual window resize operation. */
    return vs_resize_window(&pcb->vspace, rpc_window - W_BADGE_BASE, rpc_size);
}
Пример #12
0
static int
toscar_flap_handlechan1(struct nafmodule *mod, struct nafconn *conn, naf_u8_t *buf, naf_u16_t buflen)
{
	naf_sbuf_t sb;
	naf_u32_t flapver;
	naf_tlv_t *tlvh;
	int ret = HRET_FORWARD;

	naf_sbuf_init(mod, &sb, buf, buflen);

	naf_sbuf_advance(&sb, FLAPHDRLEN);

	flapver = naf_sbuf_get32(&sb);
	if (flapver != 0x00000001) {
		if (timps_oscar__debug > 0)
			dvprintf(mod, "[cid %lu] %s sent invalid FLAP version\n", conn->cid, !(conn->type & NAF_CONN_TYPE_CLIENT) ? "server" : "client");
		return HRET_ERROR;
	}

	tlvh = naf_tlv_parse(mod, &sb);

	if (FLAPHDR_LEN(buf) == 4) { /* version only */
		if (conn->type & NAF_CONN_TYPE_SERVER)
			ret = toscar_flap_handlechan1__conncomplete(mod, conn);
		else
			ret = HRET_DIGESTED; /* wait to see what else they have for us */
	} else if ((conn->type & NAF_CONN_TYPE_CLIENT) &&
			naf_tlv_get(mod, tlvh, 0x0001 /* screen name */))
		ret = toscar_flap_handlechan1__xorlogin(mod, conn, &tlvh);
	else if ((conn->type & NAF_CONN_TYPE_CLIENT) &&
			naf_tlv_get(mod, tlvh, 0x0006 /* cookie */))
		ret = toscar_flap_handlechan1__newconn(mod, conn, &tlvh);
	else {
		if (timps_oscar__debug > 0)
			dvprintf(mod, "[cid %lu] unable to determine purpose of channel 1 packet\n", conn->cid);
		ret = HRET_ERROR;
	}

	naf_tlv_free(mod, tlvh);
	return ret;
}
Пример #13
0
/*! @brief Handles memory window creation syscalls.

    The window must not be overlapping with an existing window in the client's VSpace, or
    EINVALIDPARAM will be the returned.
    
    When mapping a dataspace to a non-page aligned window, the dataspace will actually be mapped to
    the page-aligned address of the window base due to technical restrictions. Thus, the first B -
    PAGE_ALIGN(B) bytes of the mapped dataspace is unaccessible. This can have unintended effects
    when two processes map the same dataspace for sharing purposes. In other words, when sharing
    dataspaces, it's easiest for the window bases for BOTH processes to be page-aligned.
 */
seL4_CPtr
proc_create_mem_window_internal_handler(void *rpc_userptr , uint32_t rpc_vaddr , uint32_t rpc_size ,
                                        uint32_t rpc_permissions, uint32_t flags,
                                        refos_err_t* rpc_errno)
{
    struct proc_pcb *pcb = (struct proc_pcb*) rpc_userptr;
    assert(pcb && pcb->magic == REFOS_PCB_MAGIC);

    /* Check that this window does not override protected kernel memory. */
    if (rpc_vaddr >= PROCESS_KERNEL_RESERVED || PROCESS_KERNEL_RESERVED < (rpc_size + rpc_vaddr)) {
        dvprintf("memory window out of bounds, overlaps kernel reserved.\n");
        SET_ERRNO_PTR(rpc_errno, EINVALIDPARAM);
        return 0;
    }

    /* Create the window. */
    int windowID = W_INVALID_WINID;
    bool cached = (flags & W_FLAGS_UNCACHED) ? false : true;
    int error = vs_create_window(&pcb->vspace, rpc_vaddr, rpc_size, rpc_permissions, cached,
            &windowID);
    if (error != ESUCCESS || windowID == W_INVALID_WINID) {
        dvprintf("Could not create window.\n");
        SET_ERRNO_PTR(rpc_errno, error);
        return 0;
    }

    /* Find the window and return the window capability. */
    struct w_window* window = w_get_window(&procServ.windowList, windowID);
    if (!window) {
        assert(!"Successfully allocated window failed to be found. Process server bug.");
        /* Cannot recover from this situation cleanly. Shouldn't ever happen. */
        SET_ERRNO_PTR(rpc_errno, EINVALID);
        return 0;
    }

    assert(window->magic == W_MAGIC);
    assert(window->capability.capPtr);
    SET_ERRNO_PTR(rpc_errno, ESUCCESS);
    return window->capability.capPtr;
}
Пример #14
0
static int
toscar_gnroutputfunc(struct nafmodule *mod, struct gnrmsg *gm, struct gnrmsg_handler_info *gmhi)
{

	if (timps_oscar__debug > 1) {
		dvprintf(mod, "toscar_gnroutputfunc: type = %d, to = '%s'[%s](%d), from = '%s'[%s](%d), msg = (%s) '%s'\n",
				gm->type,
				gm->srcname, gm->srcnameservice,
				gmhi->srcnode ? gmhi->srcnode->metric : -1,
				gm->destname, gm->destnameservice,
				gmhi->destnode ? gmhi->destnode->metric : -1,
				gm->msgtexttype ? gm->msgtexttype : "type not specified",
				gm->msgtext);
	}

	if (gmhi->destnode->metric == GNR_NODE_METRIC_LOCAL) {
		struct nafconn *conn;

		if (!(conn = toscar__findconn(mod, gmhi->destnode->name))) {
			if (timps_oscar__debug > 0)
				dvprintf(mod, "gnroutputfunc(local): unable to find connection for local node '%s'[%s]\n", gmhi->destnode->name, gmhi->destnode->service);
			return -1;
		}

		toscar_icbm_sendincoming(mod, conn->endpoint, gm, gmhi);

	} else if (gmhi->srcnode->metric == GNR_NODE_METRIC_LOCAL) {
		struct nafconn *conn;

		if (!(conn = toscar__findconn(mod, gmhi->srcnode->name))) {
			if (timps_oscar__debug > 0)
				dvprintf(mod, "gnroutputfunc(forward): unable to find connection for local node '%s'[%s]\n", gmhi->srcnode->name, gmhi->srcnode->service);
			return -1;
		}

		toscar_icbm_sendoutgoing(mod, conn, gm, gmhi);
	}

	return 0;
}
Пример #15
0
/*! @brief Main CPIO file server message loop. Simply loops through recieving and dispatching
           messages repeatedly. */
static void
fileserv_mainloop(void)
{
    struct fs_state *s = &fileServ;
    srv_msg_t msg;
    
    while (1) {
        dvprintf("Fileserver blocking for message...\n");
        msg.message = seL4_Wait(fileServCommon->anonEP, &msg.badge);
        fileserv_handle_message(s, &msg);
        client_table_postaction(&fileServCommon->clientTable);
    }
}
Пример #16
0
static int
toscar__keepalive_matcher(struct nafmodule *mod, struct nafconn *conn, const void *ud)
{
	const time_t now = (time_t)ud;

	if (!(conn->type & NAF_CONN_TYPE_FLAP) ||
	    !(conn->type & NAF_CONN_TYPE_SERVER))
		return 0;

	if (!(conn->flags & TOSCAR_FLAG_READY))
		return 0;

	if ((now - conn->lasttx_soft) > timps_oscar__keepalive_frequency) {
		if (timps_oscar__debug > 1) {
			dvprintf(mod, "[%lu] sending nop (%d seconds since last tx)\n",
				 conn->cid,
				 now - conn->lasttx_soft);
		}
		toscar_flap_sendnop(mod, conn);
	}

	/*
	 * This closes connections that are 'stuck', at the TCP level.  If a
	 * host doesn't ack our data (to let us send our queue) for more than
	 * thirty seconds (default), then consider the connection dead. This
	 * can occur for a variety of reasons, most of them not good.
	 *
	 * The check above makes sure there's always pending data at least
	 * this often.
	 */
	if ((now - conn->lasttx_hard) > timps_oscar__txtimeout) {
		dvprintf(mod, "[%lu] connection timed out, closing (%d seconds since last hard tx)\n",
			 conn->cid,
			 now - conn->lasttx_hard);
		naf_conn_schedulekill(conn);
	}

	return 0;
}
Пример #17
0
static void freetag(struct nafmodule *mod, void *object, const char *tagname, char tagtype, void *tagdata)
{

	if (strcmp(tagname, "module.gnrmsg_outputfunc") == 0) {

		/* pointer to non-dynamic object */

	} else {

		dvprintf(mod, "freetag: unknown tag '%s'\n", tagname);

	}

	return;
}
Пример #18
0
/*! @brief Main process server loop.

    The main loop that the process server goes into and keeps looping until the process server
    is to exit and the whole system is to by shut down (which is possibly never). It blocks on the
    process server endpoint and waits for an IPC message, and then handles the dispatching of
    the message when it recieves one, before looping around and waiting for the next IPC message.

    @return Does not return, runs endlessly.
*/
static int
proc_server_loop(void)
{
    struct procserv_state *s = &procServ;
    struct procserv_msg msg = { .state = s };

    while (1) {
        dvprintf("procserv blocking for new message...\n");
        msg.message = seL4_Recv(s->endpoint.cptr, &msg.badge);
        proc_server_handle_message(s, &msg);
        s->faketime++;
    }

    return 0;
}
Пример #19
0
/*
**  say something to server and check the response
*/
void chat(char *fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    vfprintf(sfp, fmt, ap);
    va_end(ap);
  
    va_start(ap, fmt);
    dprintf("%s <-- ", mailhost);
    dvprintf(fmt, ap);
    va_end(ap);

    fflush(sfp);
    get_response();
}
Пример #20
0
static void
freetag(struct nafmodule *mod, void *object, const char *tagname, char tagtype, void *tagdata)
{

	if ((strcmp(tagname, "conn.logintlvs") == 0) ||
			(strcmp(tagname, "conn.cookietlvs") == 0))
		naf_tlv_free(mod, (naf_tlv_t *)tagdata);
	else if (strcmp(tagname, "conn.loginsnacid") == 0)
		; /* an int */
	else if (strcmp(tagname, "conn.screenname") == 0) {
		char *sn = (char *)tagdata;
		struct nafconn *conn = (struct nafconn *)object;
		struct gnrnode *node;

		if ((node = gnr_node_findbyname(sn, OSCARSERVICE)) &&
				!toscar__userhasotherclient(mod, sn, conn))
			gnr_node_offline(node, GNR_NODE_OFFLINE_REASON_DISCONNECTED);

		naf_free(mod, sn);

	} else if (strcmp(tagname, "gnrmsg.oscarmsgcookie") == 0) {
		naf_u8_t *msgck = (naf_u8_t *)tagdata;

		naf_free(mod, msgck);

	} else if (strcmp(tagname, "gnrmsg.snacid") == 0) {
		/* an int */
	} else if (strcmp(tagname, "gnrmsg.oscarmsgtlv") == 0) {
		naf_tlv_t *msgtlv = (naf_tlv_t *)tagdata;

		naf_tlv_free(mod, msgtlv);

	} else if (strcmp(tagname, "gnrmsg.extraoscartlvs") == 0) {
		naf_tlv_t *tlvs = (naf_tlv_t *)tagdata;

		naf_tlv_free(mod, tlvs);

	} else if (strcmp(tagname, "gnrmsg.srcuserinfo") == 0) {
		struct touserinfo *toui = (struct touserinfo *)tagdata;

		touserinfo_free(mod, toui);

	} else
		dvprintf(mod, "freetag: unknown tagname '%s'\n", tagname);

	return;
}
Пример #21
0
static void dumpbox(struct nafmodule *mod, const char *prefix, naf_conn_cid_t cid, unsigned char *buf, int len)
{
	int z = 0, x, y;
	char tmpstr[256];

	while (z<len) {
		x = snprintf(tmpstr, sizeof(tmpstr), "%sput, %d bytes to cid %ld:      ", prefix, len, cid);
		for (y = 0; y < 8; y++) {
			if (z<len) {
				snprintf(tmpstr+x, sizeof(tmpstr)-strlen(tmpstr), "%02x ", buf[z]);
				z++;
				x += 3;
			} else
				break;
		}
		dvprintf(mod, "%s\n", tmpstr);
	}
}
Пример #22
0
/*! @brief Handles server pager setup syscalls.

    A dataserver calls the process server with this call in order to set up to be the pager of
    one of its client processes for a particular window. The client process is identified by the
    passing of its liveliness cap. All faults for the client's process which happen at that window
    will then be delegated to the dataserver to be handled.
*/
refos_err_t
proc_register_as_pager_handler(void *rpc_userptr , seL4_CPtr rpc_window ,
                               seL4_CPtr rpc_faultNotifyEP , seL4_Word* rpc_winID) 
{
    struct proc_pcb *pcb = (struct proc_pcb*) rpc_userptr;
    struct procserv_msg *m = (struct procserv_msg*) pcb->rpcClient.userptr;
    assert(pcb && pcb->magic == REFOS_PCB_MAGIC);

    if (!check_dispatch_caps(m, 0x00000001, 2)) {
        return EINVALIDPARAM;
    }

    /* Retrieve and verify the window cap. */
    if (!dispatcher_badge_window(rpc_window)) {
        ROS_WARNING("Invalid window badge.");
        return EINVALIDPARAM;
    }
    struct w_window *win = w_get_window(&procServ.windowList, rpc_window - W_BADGE_BASE);
    if (!win) {
        ROS_ERROR("invalid window ID.");
        return EINVALIDPARAM;
    }
    assert(win->magic == W_MAGIC);

    /* Copy out the fault endpoint. */
    seL4_CPtr faultNotifyEP = dispatcher_copyout_cptr(rpc_faultNotifyEP);
    if (!faultNotifyEP) {
        dvprintf("could not copy out faultNotifyEP.");
        return EINVALIDPARAM; 
    }

    /* Set the pager endpoint. If there was anything else mapped to this window, it will be
       unmapped. */
    cspacepath_t faultNotifyEPPath;
    vka_cspace_make_path(&procServ.vka, faultNotifyEP, &faultNotifyEPPath);
    w_set_pager_endpoint(win, faultNotifyEPPath, pcb->pid);

    if (rpc_winID) {
        (*rpc_winID) = win->wID;
    }
    return ESUCCESS;
}
Пример #23
0
static void freenode(struct gnrnode *gn, int reason)
{

	{
		struct gnr_event_ei_nodechange ei;

		memset(&ei, 0, sizeof(struct gnr_event_ei_nodechange));

		ei.reason = reason;

		gnr_event_throw_withnode(GNR_EVENT_NODEDOWN, gn, &ei);
	}

#if 0
	dvprintf(gnr__module, "user offline: %s[%s][%s][%s%s%s] -- %s%s%s\n",
			gn->name,
			gn->service,
			gn->ownermod ? gn->ownermod->name : "unknown",
			(gn->metric == GNR_NODE_METRIC_LOCAL) ? "local" : "",
			GNR_NODE_METRIC_ISPEERED(gn->metric) ? "peer" : "",
			(gn->metric == GNR_NODE_METRIC_MAX) ? "remote" : "",
			(reason == GNR_NODE_OFFLINE_REASON_TIMEOUT) ? "timed out" : "",
			(reason == GNR_NODE_OFFLINE_REASON_DISCONNECTED) ? "disconnected" : "",
			((reason != GNR_NODE_OFFLINE_REASON_TIMEOUT) && (reason != GNR_NODE_OFFLINE_REASON_DISCONNECTED)) ? "unknown reason" : "");
#endif

	gnr__nodestats.total--;
	if (gn->metric == GNR_NODE_METRIC_LOCAL)
		gnr__nodestats.local--;
	else if (gn->metric == GNR_NODE_METRIC_MAX)
		gnr__nodestats.external--;
	else
		gnr__nodestats.peered--;

	naf_tag_freelist(&gn->taglistv, gn);
	naf_free(gnr__module, gn->name);
	naf_free(gnr__module, gn->service);
	naf_free(gnr__module, gn);

	return;
}
Пример #24
0
int
timer_write_handler(void *rpc_userptr , seL4_CPtr rpc_dspace_fd , uint32_t rpc_offset ,
                         rpc_buffer_t rpc_buf , uint32_t rpc_count)
{
    struct srv_client *c = (struct srv_client *) rpc_userptr;
    assert(c && c->magic == TIMESERV_CLIENT_MAGIC);
    assert(rpc_dspace_fd == TIMESERV_DSPACE_BADGE_TIMER);

    if (rpc_buf.count < sizeof(uint64_t)) {
        return -EINVALIDPARAM;
    }

    /* Writing to the timer dataspace results in a sleep call. */
    uint64_t timeWait = *( (uint64_t*) (rpc_buf.data) );
    dvprintf("timer_write_handler client waiting for %llu nanoseconds.\n", timeWait);

    int error = device_timer_save_caller_as_waiter(&timeServ.devTimer, c, timeWait);
    if (error == ESUCCESS) {
        c->rpcClient.skip_reply = true;
    }
    return -error;
}
Пример #25
0
/* Remetric'ing is a complicated thing. It's probably broken. */
int gnr_node_remetric(struct gnrnode *gn, int newmetric)
{

	if (!gn)
		return -1;

	if (gn->metric < newmetric)
		dvprintf(gnr__module, "BUG: gnr_node_remetric asked to make node %s[%s] farther away (new = %d, old = %d)\n", gn->name, gn->service, newmetric, gn->metric);


	if (gn->metric == GNR_NODE_METRIC_LOCAL)
		gnr__nodestats.local--;
	else if (gn->metric == GNR_NODE_METRIC_MAX)
		gnr__nodestats.external--;
	else
		gnr__nodestats.peered--;


	gn->metric = newmetric;


	if (gn->metric == GNR_NODE_METRIC_LOCAL)
		gnr__nodestats.local++;
	else if (gn->metric == GNR_NODE_METRIC_MAX)
		gnr__nodestats.external++;
	else
		gnr__nodestats.peered++;


	if (gn->metric == GNR_NODE_METRIC_LOCAL)
		gn->ttl = -1;
	else
		gn->ttl = GNR_NODE_TTL_DEFAULT;


	gnr_node_usehit(gn);

	return 0;
}
Пример #26
0
static int
toscar__detacholdconns__matcher(struct nafmodule *mod, struct nafconn *conn, const void *udata)
{
	const char *sn = (const char *)udata;
	char *cursn = NULL;

	if (!(conn->type & NAF_CONN_TYPE_SERVER))
		return 0;
	if (conn->endpoint)
		return 0;

	if ((naf_conn_tag_fetch(mod, conn, "conn.screenname", NULL, (void **)&cursn) == -1) || !cursn)
		return 0;
	if (toscar_sncmp(sn, cursn) != 0)
		return 0;

	if (timps_oscar__debug) {
		dvprintf(mod, "disconnecting old server connection %lu for '%s'\n", conn->cid, cursn);
	}

	naf_conn_schedulekill(conn);

	return 0; /* keep going */
}
Пример #27
0
/*! @brief Handles client VM fault messages sent by the kernel.

    Handles the VM fault message by looking up the details of the window that it faulted in, and
    decides whether this fault should be delegated to an external dataspace server for paging
    or content initalisation, or be handled internally by the process server's own dataspace
    implementation for RAM, or is an invalid memory access.
    
    In the case of an invalid memory access, or if the process server runs out of RAM, then
    the fault is unable to be handled and the faulting process is blocked indefinitely.

    @param m The recieved IPC fault message from the kernel.
    @param f The VM fault message info struct.
*/
static void
handle_vm_fault(struct procserv_msg *m, struct procserv_vmfault_msg *f)
{
    assert(f && f->pcb);
    dvprintf("# Process server recieved PID %d VM fault\n", f->pcb->pid);
    dvprintf("# %s %s fault at 0x%x, Instruction Pointer 0x%x, Fault Status Register 0x%x\n",
            f->instruction ? "Instruction" : "Data", f->read ? "read" : "write",
            f->faultAddr, f->pc, f->fsr);

    /* Thread should never be fault blocked (or else how did this VM fault even happen?). */
    if (f->pcb->faultReply.capPtr != 0) {
        ROS_ERROR("(how did this VM fault even happen? Check book-keeping.\n");
        output_segmentation_fault("Process should already be fault-blocked.", f);
        return;
    }

    /* Check faulting vaddr in segment windows. */
    struct w_associated_window *aw = w_associate_find(&f->pcb->vspace.windows, f->faultAddr);
    if (!aw) {
        output_segmentation_fault("invalid memory window segment", f);
        return;
    }

    /* Retrieve the associated window. */
    struct w_window *window = w_get_window(&procServ.windowList, aw->winID);
    if (!window) {
        output_segmentation_fault("invalid memory window - procserv book-keeping error.", f);
        assert(!"Process server could not find window - book-keeping error.");
        return;
    }

    /* Check window permissions. */
    if (f->read && !(window->permissions | W_PERMISSION_READ)) {
        output_segmentation_fault("no read access permission to window.", f);
        return;
    }
    if (!f->read && !(window->permissions | W_PERMISSION_WRITE)) {
        output_segmentation_fault("no write access permission to window.", f);
        return;
    }

    /* Check that there isn't a page entry already mapped. */
    cspacepath_t pageEntry = vs_get_frame(&f->pcb->vspace, f->faultAddr);
    if (pageEntry.capPtr != 0) {
        output_segmentation_fault("entry already occupied; book-keeping error.", f);
        return;
    }

    /* Handle the dispatch request depending on window mode. */
    int error = EINVALID;
    switch (window->mode) {
        case W_MODE_EMPTY:
            output_segmentation_fault("fault in empty window.", f);
            break;
        case W_MODE_ANONYMOUS:
            error = handle_vm_fault_dspace(m, f, aw, window);
            break;
        case W_MODE_PAGER:
            error = handle_vm_fault_pager(m, f, aw, window);
            break;
        default:
            assert(!"Invalid window mode. Process server bug.");
            break;
    }

    /* Reply to the faulting process to unblock it. */
    if (error == ESUCCESS) {
        seL4_Reply(_dispatcherEmptyReply);
    }
}
Пример #28
0
/*! @brief Handles faults on windows mapped to anonymous memory.

    This function is responsible for handling VM faults on windows which have been mapped to the
    process server's own anonymous dataspaces, including ones that have been content-initialised.

    If the dataspace has been set to content-initialised, then we will need to delegate and save the
    reply cap to reply to it once the content has been initialised. If it has not been initialised
    we simply map the dataspace page and reply.

    @param m The recieved IPC fault message from the kernel.
    @param f The VM fault message info struct.
    @param aw Found associated window of the faulting address & client.
    @param window The window structure of the faulting address & client.
    @return ESUCCESS on success, refos_err_t otherwise.
*/
static int
handle_vm_fault_dspace(struct procserv_msg *m, struct procserv_vmfault_msg *f,
        struct w_associated_window *aw, struct w_window *window)
{
    assert(f && f->pcb);
    assert(aw && window && window->mode == W_MODE_ANONYMOUS);

    vaddr_t dspaceOffset = (f->faultAddr + window->ramDataspaceOffset) -
                           REFOS_PAGE_ALIGN(aw->offset);
    struct ram_dspace *dspace = window->ramDataspace;
    assert(dspace && dspace->magic == RAM_DATASPACE_MAGIC);

    dvprintf("# PID %d VM fault ―――――▶ anon RAM dspace %d\n", f->pcb->pid, dspace->ID);

    if (dspace->contentInitEnabled) {
        /* Data space is backed by external content. Content initialisation delegation. */
        int contentInitState =  ram_dspace_need_content_init(dspace, dspaceOffset);
        if (contentInitState < 0) {
            output_segmentation_fault("Failed to retrieve content-init state.", f);
            return EINVALID;
        }
        if (contentInitState == true) {
            /* Content has not yet been initialised so we delegate. */
            if (f->faultAddr + window->ramDataspaceOffset >= aw->offset + aw->size) {
                output_segmentation_fault("Fault address out of range!", f);
                return EINVALID;
            }

            /* Find the pager's PCB. */
            assert(dspace->contentInitPID != PID_NULL);
            struct proc_pcb* cinitPCB = pid_get_pcb(&procServ.PIDList, dspace->contentInitPID);
            if (!cinitPCB) {
                output_segmentation_fault("Invalid content initialiser PID.", f);
                return EINVALID;
            }
            if (!dspace->contentInitEP.capPtr) {
                output_segmentation_fault("Invalid content-init endpoint!", f);
                return EINVALID;
            }

            /* Save the reply endpoint. */
            int error = ram_dspace_add_content_init_waiter_save_current_caller(dspace,
                    dspaceOffset);
            if (error != ESUCCESS) {
                output_segmentation_fault("Failed to save reply cap as dspace waiter!", f);
                return EINVALID;
            }

            /* Set up and send the fault notification. */
            struct proc_notification vmFaultNotification;
            vmFaultNotification.magic = PROCSERV_NOTIFICATION_MAGIC;
            vmFaultNotification.label = PROCSERV_NOTIFY_CONTENT_INIT;
            vmFaultNotification.arg[0] = dspace->ID;
            vmFaultNotification.arg[1] = REFOS_PAGE_ALIGN(dspaceOffset);

            fault_delegate_notification(f, cinitPCB, dspace->contentInitEP, vmFaultNotification,
                                        false);

            /* Return an error here to avoid resuming the client. */
            return EDELEGATED;
        }

        /* Fallthrough to normal dspace mapping if content-init state is set to already provided. */
    }

    /* Get the page at the dataspaceOffset into the dataspace. */
    seL4_CPtr frame = ram_dspace_get_page(dspace, dspaceOffset);
    if (!frame) {
        output_segmentation_fault("Out of memory to allocate page or read off end of dspace.", f);
        return ENOMEM;
    }

    /* Map this frame into the client process's page directory. */
    int error = vs_map(&f->pcb->vspace, f->faultAddr, &frame, 1);
    if (error != ESUCCESS) {
        output_segmentation_fault("Failed to map frame into client's vspace at faultAddr.", f);
        return error;
    }

    return ESUCCESS;
}
Пример #29
0
int
srv_dispatch_notification(srv_common_t *srv, srv_common_notify_handler_callbacks_t callbacks)
{
    assert(srv && srv->magic == SRV_MAGIC);

    /* Allocate a notification structure. */
    struct proc_notification *notification = malloc(sizeof(struct proc_notification)); 
    if (!notification) {
        dprintf("Out of memory while creating notification struct.\n");
        return DISPATCH_ERROR;
    }

    dvprintf("%s recieved fault notification!\n", srv->config.serverName);
    data_mapping_t *nb = &srv->notifyBuffer;
    uint32_t bytesRead = 0;
    int error = DISPATCH_PASS;

    while (1) {
        bytesRead = 0;

        error = refos_share_read (
                (char*) notification, sizeof(struct proc_notification),
                nb->vaddr, nb->size,
                &srv->notifyBufferStart, &bytesRead
        );
        if (!error && bytesRead == 0) {
            /* No more notifications to read. */
            break;
        }

        if (error || bytesRead != sizeof(struct proc_notification)) {
            /* Error during reading notification. */
            dprintf("Could not read information from notification buffer!\n");
            dprintf("    error = %d\n, read = %d", error, bytesRead);
            free(notification);
            return DISPATCH_ERROR;
        }

        /* Paranoid sanity check here. */
        assert(notification->magic == PROCSERV_NOTIFICATION_MAGIC);

        error = DISPATCH_ERROR;
        switch (notification->label) {
        case PROCSERV_NOTIFY_FAULT_DELEGATION:
            if (callbacks.handle_server_fault) {
                error = callbacks.handle_server_fault(notification);
                break;
            }
        case PROCSERV_NOTIFY_CONTENT_INIT:
            if (callbacks.handle_server_content_init) {
                error = callbacks.handle_server_content_init(notification);
                break;
            }
        case PROCSERV_NOTIFY_DEATH:
            if (callbacks.handle_server_death_notification) {
                error = callbacks.handle_server_death_notification(notification);
                break;
            }
        default:
            /* Should never get here. */
            ROS_WARNING("Unknown notification.\n");
            assert(!"Unknown notification.");
            break;
        }
    }

    if (error) {
        ROS_WARNING("Notification handling error on %s: %d\n", srv->config.serverName, error);
    }

    free(notification);
    return error;
}
Пример #30
0
int
toscar_flap_handleread(struct nafmodule *mod, struct nafconn *conn)
{
	naf_u8_t *buf;
	int buflen;
	int hret = HRET_FORWARD;

	if (naf_conn_takeread(conn, &buf, &buflen) == -1)
		return -1;

	if (FLAPHDR_MAGIC(buf) != FLAP_MAGIC) {
		if (timps_oscar__debug > 0)
			dvprintf(mod, "[cid %lu] FLAP packet did not start with correct magic\n", conn->cid);
		goto errout;
	}

	/* XXX check seqnums */

	if (! ( (FLAPHDR_CHAN(buf) == 0x01) ||
				(FLAPHDR_CHAN(buf) == 0x02) ||
				(FLAPHDR_CHAN(buf) == 0x04) ||
				(FLAPHDR_CHAN(buf) == 0x05) ) ) {
		if (timps_oscar__debug > 0)
			dvprintf(mod, "[cid %lu] FLAP packet on invalid channel\n", conn->cid);
		goto errout;
	}

	if (FLAPHDR_LEN(buf) > MAXSNACLEN) {
		if (timps_oscar__debug > 0)
			dvprintf(mod, "[cid %lu] FLAP packet contained invalid length\n", conn->cid);
		goto errout;
	}

	if (buflen != (FLAPHDR_LEN(buf) + FLAPHDRLEN)) {
		if (naf_conn_reqread(conn, buf, buflen + FLAPHDR_LEN(buf), buflen) == -1) {
			if (timps_oscar__debug > 0)
				dvprintf(mod, "[cid %lu] naf refused further read request\n", conn->cid);
			goto errout;
		}
		return 0; /* continue later */
	}

	if (timps_oscar__debug > 1)
		dvprintf(mod, "[cid %lu] received full FLAP packet on channel 0x%02x, seqnum 0x%04lx, length 0x%04lx (%d bytes)\n", conn->cid, FLAPHDR_CHAN(buf), FLAPHDR_SEQNUM(buf), FLAPHDR_LEN(buf), FLAPHDR_LEN(buf));


	if (FLAPHDR_CHAN(buf) == 0x01)
		hret = toscar_flap_handlechan1(mod, conn, buf, (naf_u16_t)buflen);
	else if (FLAPHDR_CHAN(buf) == 0x02)
		hret = toscar_flap_handlesnac(mod, conn, buf + FLAPHDRLEN, (naf_u16_t)(buflen - FLAPHDRLEN));
	else if (FLAPHDR_CHAN(buf) == 0x04)
		hret = toscar_flap_handlechan4(mod, conn, buf, (naf_u16_t)buflen);
	else if (FLAPHDR_CHAN(buf) == 0x05)
		hret = toscar_flap_handlechan5(mod, conn, buf, (naf_u16_t)buflen);


	if (hret == HRET_ERROR)
		goto errout;
	else if ((hret == HRET_FORWARD) && conn->endpoint) {
		if (toscar_flap__sendraw(mod, conn->endpoint, buf, (naf_u16_t)buflen) == -1)
			goto errout;
		buf = NULL; /* consumed by sendraw */
	}
	/*
	 * HRET_DIGESTED means the packet was processed but should not be
	 * forwarded -- it was not consumed, in the memory management sense, so
	 * we can reuse it.
	 */

	/* go again... */
	if (toscar_flap__reqflap(mod, conn, buf) == -1)
		goto errout;

	return 0;
errout:
	naf_free(mod, buf);
	return -1;
}