1139823Simp/*-
274060Sbp * Copyright (c) 1999, 2000, 2001 Boris Popov
351852Sbp * All rights reserved.
451852Sbp *
551852Sbp * Redistribution and use in source and binary forms, with or without
651852Sbp * modification, are permitted provided that the following conditions
751852Sbp * are met:
851852Sbp * 1. Redistributions of source code must retain the above copyright
951852Sbp *    notice, this list of conditions and the following disclaimer.
1051852Sbp * 2. Redistributions in binary form must reproduce the above copyright
1151852Sbp *    notice, this list of conditions and the following disclaimer in the
1251852Sbp *    documentation and/or other materials provided with the distribution.
1351852Sbp *
1451852Sbp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1551852Sbp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1651852Sbp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1751852Sbp * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1851852Sbp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1951852Sbp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2051852Sbp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2151852Sbp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2251852Sbp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2351852Sbp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2451852Sbp * SUCH DAMAGE.
2551852Sbp */
26116189Sobrien
27116189Sobrien#include <sys/cdefs.h>
28116189Sobrien__FBSDID("$FreeBSD$");
29116189Sobrien
3051852Sbp#include <sys/param.h>
3176166Smarkm#include <sys/systm.h>
3251852Sbp#include <sys/errno.h>
33112564Sjhb#include <sys/eventhandler.h>
3476166Smarkm#include <sys/kernel.h>
3576166Smarkm#include <sys/lock.h>
3676166Smarkm#include <sys/malloc.h>
3751852Sbp#include <sys/proc.h>
3874060Sbp#include <sys/sysctl.h>
3951852Sbp#include <sys/time.h>
4051852Sbp
4151852Sbp#include <netncp/ncp.h>
4251852Sbp#include <netncp/ncp_conn.h>
4351852Sbp#include <netncp/ncp_sock.h>
4451852Sbp#include <netncp/ncp_subr.h>
4551852Sbp#include <netncp/ncp_rq.h>
4651852Sbp#include <netncp/ncp_ncp.h>
4751852Sbp#include <netncp/nwerror.h>
4851852Sbp
4951852Sbpint ncp_debuglevel = 0;
5051852Sbp
5151852Sbpstruct callout_handle ncp_timer_handle;
52112564Sjhbstatic eventhandler_tag ncp_exit_tag;
5351852Sbp
54112564Sjhbstatic void ncp_at_exit(void *arg, struct proc *p);
5551852Sbpstatic void ncp_timer(void *arg);
5651852Sbp
5751852Sbp/*
5851852Sbp * duplicate string from user space. It should be very-very slow.
5951852Sbp */
6051852Sbpchar *
6151852Sbpncp_str_dup(char *s) {
6251852Sbp	char *p, bt;
6351852Sbp	int len = 0;
6451852Sbp
6551852Sbp	for (p = s;;p++) {
6651852Sbp		if (copyin(p, &bt, 1)) return NULL;
6751852Sbp		len++;
6851852Sbp		if (bt == 0) break;
6951852Sbp	}
70184205Sdes	p = malloc(len, M_NCPDATA, M_WAITOK);
7151852Sbp	copyin(s, p, len);
7251852Sbp	return p;
7351852Sbp}
7451852Sbp
7551852Sbp
7651852Sbpvoid
77112564Sjhbncp_at_exit(void *arg, struct proc *p)
7874060Sbp{
7951852Sbp	struct ncp_conn *ncp, *nncp;
80111577Sfjoe	struct thread *td;
8151852Sbp
82126941Speter	mtx_lock(&Giant);
83111577Sfjoe	FOREACH_THREAD_IN_PROC(p, td) {
84111577Sfjoe		if (ncp_conn_putprochandles(td) == 0)
85111577Sfjoe			continue;
8651852Sbp
87111577Sfjoe		ncp_conn_locklist(LK_EXCLUSIVE, td);
88111577Sfjoe		for (ncp = SLIST_FIRST(&conn_list); ncp; ncp = nncp) {
89111577Sfjoe			nncp = SLIST_NEXT(ncp, nc_next);
90111577Sfjoe			if (ncp_conn_lock(ncp, td, td->td_ucred,
91111577Sfjoe					  NCPM_READ | NCPM_EXECUTE | NCPM_WRITE))
92111577Sfjoe				continue;
93111577Sfjoe			if (ncp_conn_free(ncp) != 0)
94111577Sfjoe				ncp_conn_unlock(ncp, td);
95111577Sfjoe		}
96111577Sfjoe		ncp_conn_unlocklist(td);
9751852Sbp	}
98126941Speter	mtx_unlock(&Giant);
9951852Sbp}
10051852Sbp
10151852Sbpint
10274060Sbpncp_init(void)
10374060Sbp{
10451852Sbp	ncp_conn_init();
105112564Sjhb	ncp_exit_tag = EVENTHANDLER_REGISTER(process_exit, ncp_at_exit, NULL,
106112564Sjhb	    EVENTHANDLER_PRI_ANY);
107111577Sfjoe	ncp_timer_handle = timeout(ncp_timer, NULL, NCP_TIMER_TICK);
10851852Sbp	return 0;
10951852Sbp}
11051852Sbp
11174060Sbpint
11274060Sbpncp_done(void)
11374060Sbp{
11474060Sbp	int error;
11574060Sbp
11674060Sbp	error = ncp_conn_destroy();
11774060Sbp	if (error)
11874060Sbp		return error;
119111577Sfjoe	untimeout(ncp_timer, NULL, ncp_timer_handle);
120112564Sjhb	EVENTHANDLER_DEREGISTER(process_exit, ncp_exit_tag);
12174060Sbp	return 0;
12251852Sbp}
12351852Sbp
12451852Sbp
12551852Sbp/* tick every second and check for watch dog packets and lost connections */
12651852Sbpstatic void
12774060Sbpncp_timer(void *arg)
12874060Sbp{
12951852Sbp	struct ncp_conn *conn;
13051852Sbp
13151852Sbp	if(ncp_conn_locklist(LK_SHARED | LK_NOWAIT, NULL) == 0) {
13251852Sbp		SLIST_FOREACH(conn, &conn_list, nc_next)
13351852Sbp			ncp_check_conn(conn);
13451852Sbp		ncp_conn_unlocklist(NULL);
13551852Sbp	}
136111577Sfjoe	ncp_timer_handle = timeout(ncp_timer, NULL, NCP_TIMER_TICK);
13751852Sbp}
138