Example #1
0
int
kldload(struct proc* p, struct kldload_args* uap)
{
    char* filename = NULL, *modulename;
    linker_file_t lf;
    int error = 0;

    p->p_retval[0] = -1;

    if (securelevel > 0)
	return EPERM;

    if (error = suser(p->p_ucred, &p->p_acflag))
	return error;

    filename = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
    if (error = copyinstr(SCARG(uap, file), filename, MAXPATHLEN, NULL))
	goto out;

    /* Can't load more than one module with the same name */
    modulename = rindex(filename, '/');
    if (modulename == NULL)
	modulename = filename;
    if (linker_find_file_by_name(modulename)) {
	error = EEXIST;
	goto out;
    }

    if (error = linker_load_file(filename, &lf))
	goto out;

    lf->userrefs++;
    p->p_retval[0] = lf->id;

out:
    if (filename)
	free(filename, M_TEMP);
    return error;
}
Example #2
0
static void
ngc_send(netmsg_t netmsg)
{
	struct socket *so = netmsg->send.base.nm_so;
	struct mbuf *m = netmsg->send.nm_m;
	struct sockaddr *addr = netmsg->send.nm_addr;
	struct mbuf *control = netmsg->send.nm_control;
	struct ngpcb *const pcbp = sotongpcb(so);
	struct sockaddr_ng *const sap = (struct sockaddr_ng *) addr;
	struct ng_mesg *msg;
	struct mbuf *m0;
	item_p item;
	char *path = NULL;
	int len, error = 0;
	struct ng_apply_info *apply;

#ifdef	NOTYET
	if (control && (error = ng_internalize(control, td))) {
		if (pcbp->sockdata == NULL) {
			error = ENOTCONN;
			goto release;
		}
	}
#else	/* NOTYET */
	if (control) {
		error = EINVAL;
		goto release;
	}
#endif	/* NOTYET */

	/* Require destination as there may be >= 1 hooks on this node. */
	if (addr == NULL) {
		error = EDESTADDRREQ;
		goto release;
	}

	/*
	 * Allocate an expendable buffer for the path, chop off
	 * the sockaddr header, and make sure it's NUL terminated.
	 */
	len = sap->sg_len - 2;
	path = kmalloc(len + 1, M_NETGRAPH_PATH, M_WAITOK);
	bcopy(sap->sg_data, path, len);
	path[len] = '\0';

	/*
	 * Move the actual message out of mbufs into a linear buffer.
	 * Start by adding up the size of the data. (could use mh_len?)
	 */
	for (len = 0, m0 = m; m0 != NULL; m0 = m0->m_next)
		len += m0->m_len;

	/*
	 * Move the data into a linear buffer as well.
	 * Messages are not delivered in mbufs.
	 */
	msg = kmalloc(len + 1, M_NETGRAPH_MSG, M_WAITOK);
	m_copydata(m, 0, len, (char *)msg);

	if (msg->header.version != NG_VERSION) {
		kfree(msg, M_NETGRAPH_MSG);
		error = EINVAL;
		goto release;
	}

	/*
	 * Hack alert!
	 * We look into the message and if it mkpeers a node of unknown type, we
	 * try to load it. We need to do this now, in syscall thread, because if
	 * message gets queued and applied later we will get panic.
	 */
	if (msg->header.typecookie == NGM_GENERIC_COOKIE &&
	    msg->header.cmd == NGM_MKPEER) {
		struct ngm_mkpeer *const mkp = (struct ngm_mkpeer *) msg->data;
		struct ng_type *type;

		if ((type = ng_findtype(mkp->type)) == NULL) {
			char filename[NG_TYPESIZ + 3];
			linker_file_t fileid;

			if (!linker_api_available()) {
				error = ENXIO;
				goto done;
			}

			/* Not found, try to load it as a loadable module. */
			ksnprintf(filename, sizeof(filename), "ng_%s.ko",
			    mkp->type);
			error = linker_load_file(filename, &fileid);
			if (error != 0) {
				kfree(msg, M_NETGRAPH_MSG);
				goto release;
			}

			/* See if type has been loaded successfully. */
			if ((type = ng_findtype(mkp->type)) == NULL) {
				kfree(msg, M_NETGRAPH_MSG);
				(void)linker_file_unload(fileid);
				error =  ENXIO;
				goto release;
			}
		}
	}

	item = ng_package_msg(msg, NG_WAITOK);
	if ((error = ng_address_path((pcbp->sockdata->node), item, path, 0))
	    != 0) {
#ifdef TRACE_MESSAGES
		kprintf("ng_address_path: errx=%d\n", error);
#endif
		goto release;
	}

#ifdef TRACE_MESSAGES
	kprintf("[%x]:<---------[socket]: c=<%d>cmd=%x(%s) f=%x #%d (%s)\n",
		item->el_dest->nd_ID,
		msg->header.typecookie,
		msg->header.cmd,
		msg->header.cmdstr,
		msg->header.flags,
		msg->header.token,
		item->el_dest->nd_type->name);
#endif
	SAVE_LINE(item);

	/*
	 * We do not want the user thread to return from syscall until the
	 * item is processed by destination node.  We register callback
	 * on the item, which will reply to the user thread when item
	 * was applied.
	 */
	apply = ng_alloc_apply();
	bzero(apply, sizeof(*apply));
	apply->apply = ng_socket_item_applied;
	apply->context = &netmsg->send.base.lmsg;
	item->apply = apply;

	error = ng_snd_item(item, NG_PROGRESS);

release:
	if (path != NULL)
		kfree(path, M_NETGRAPH_PATH);
	if (control != NULL)
		m_freem(control);
	if (m != NULL)
		m_freem(m);
done:
	if (error != EINPROGRESS)
		lwkt_replymsg(&netmsg->send.base.lmsg, error);
}