1 /*-
2  * Copyright (c) 1999, 2000, 2001 Boris Popov
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD: stable/9/sys/netncp/ncp_subr.c 206361 2010-04-07 16:50:38Z joel $");
29 
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/errno.h>
33 #include <sys/eventhandler.h>
34 #include <sys/kernel.h>
35 #include <sys/lock.h>
36 #include <sys/malloc.h>
37 #include <sys/proc.h>
38 #include <sys/sysctl.h>
39 #include <sys/time.h>
40 
41 #include <netncp/ncp.h>
42 #include <netncp/ncp_conn.h>
43 #include <netncp/ncp_sock.h>
44 #include <netncp/ncp_subr.h>
45 #include <netncp/ncp_rq.h>
46 #include <netncp/ncp_ncp.h>
47 #include <netncp/nwerror.h>
48 
49 int ncp_debuglevel = 0;
50 
51 struct callout_handle ncp_timer_handle;
52 static eventhandler_tag ncp_exit_tag;
53 
54 static void ncp_at_exit(void *arg, struct proc *p);
55 static void ncp_timer(void *arg);
56 
57 /*
58  * duplicate string from user space. It should be very-very slow.
59  */
60 char *
ncp_str_dup(char * s)61 ncp_str_dup(char *s) {
62 	char *p, bt;
63 	int len = 0;
64 
65 	for (p = s;;p++) {
66 		if (copyin(p, &bt, 1)) return NULL;
67 		len++;
68 		if (bt == 0) break;
69 	}
70 	p = malloc(len, M_NCPDATA, M_WAITOK);
71 	copyin(s, p, len);
72 	return p;
73 }
74 
75 
76 void
ncp_at_exit(void * arg,struct proc * p)77 ncp_at_exit(void *arg, struct proc *p)
78 {
79 	struct ncp_conn *ncp, *nncp;
80 	struct thread *td;
81 
82 	mtx_lock(&Giant);
83 	FOREACH_THREAD_IN_PROC(p, td) {
84 		if (ncp_conn_putprochandles(td) == 0)
85 			continue;
86 
87 		ncp_conn_locklist(LK_EXCLUSIVE, td);
88 		for (ncp = SLIST_FIRST(&conn_list); ncp; ncp = nncp) {
89 			nncp = SLIST_NEXT(ncp, nc_next);
90 			if (ncp_conn_lock(ncp, td, td->td_ucred,
91 					  NCPM_READ | NCPM_EXECUTE | NCPM_WRITE))
92 				continue;
93 			if (ncp_conn_free(ncp) != 0)
94 				ncp_conn_unlock(ncp, td);
95 		}
96 		ncp_conn_unlocklist(td);
97 	}
98 	mtx_unlock(&Giant);
99 }
100 
101 int
ncp_init(void)102 ncp_init(void)
103 {
104 	ncp_conn_init();
105 	ncp_exit_tag = EVENTHANDLER_REGISTER(process_exit, ncp_at_exit, NULL,
106 	    EVENTHANDLER_PRI_ANY);
107 	ncp_timer_handle = timeout(ncp_timer, NULL, NCP_TIMER_TICK);
108 	return 0;
109 }
110 
111 int
ncp_done(void)112 ncp_done(void)
113 {
114 	int error;
115 
116 	error = ncp_conn_destroy();
117 	if (error)
118 		return error;
119 	untimeout(ncp_timer, NULL, ncp_timer_handle);
120 	EVENTHANDLER_DEREGISTER(process_exit, ncp_exit_tag);
121 	return 0;
122 }
123 
124 
125 /* tick every second and check for watch dog packets and lost connections */
126 static void
ncp_timer(void * arg)127 ncp_timer(void *arg)
128 {
129 	struct ncp_conn *conn;
130 
131 	if(ncp_conn_locklist(LK_SHARED | LK_NOWAIT, NULL) == 0) {
132 		SLIST_FOREACH(conn, &conn_list, nc_next)
133 			ncp_check_conn(conn);
134 		ncp_conn_unlocklist(NULL);
135 	}
136 	ncp_timer_handle = timeout(ncp_timer, NULL, NCP_TIMER_TICK);
137 }
138