1 #ifndef CLICK_LLRPC_H
2 #define CLICK_LLRPC_H
3 #if CLICK_LINUXMODULE
4 # include <click/cxxprotect.h>
5 CLICK_CXX_PROTECT
6 # include <linux/errno.h>
7 # include <linux/ioctl.h>
8 # include <asm/uaccess.h>
9 CLICK_CXX_UNPROTECT
10 # include <click/cxxunprotect.h>
11 #elif CLICK_BSDMODULE
12 # include <sys/errno.h>
13 # include <sys/ioccom.h>
14 #else
15 # include <errno.h>
16 # include <sys/ioctl.h>
17 #endif
18 
19 /* Click low-level RPC interface */
20 
21 /* Ioctl numbers are not consistent across platforms unless you #define
22    HAVE_PORTABLE_LLRPC. */
23 #define _CLICK_NET_IOC_VOID	0x20000000
24 #define _CLICK_NET_IOC_OUT	0x40000000
25 #define _CLICK_NET_IOC_IN	0x80000000
26 #if HAVE_PORTABLE_LLRPC || !defined(__linux__)
27 # define _CLICK_IOC_VOID	_CLICK_NET_IOC_VOID
28 # define _CLICK_IOC_OUT		_CLICK_NET_IOC_OUT
29 # define _CLICK_IOC_IN		_CLICK_NET_IOC_IN
30 #else
31 # define _CLICK_IOC_VOID	(_IOC_NONE << _IOC_DIRSHIFT)
32 # define _CLICK_IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
33 # define _CLICK_IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
34 #endif
35 #define _CLICK_IOC_BASE_MASK	0x0FFFFFFF
36 #define _CLICK_IOC_SAFE		0x00008000
37 #define _CLICK_IOC_FLAT		0x00004000
38 #define _CLICK_IOC_SIZE(io)	((io) >> 16 & 0xFFF)
39 
40 /* _CLICK_IO[S]: data transfer direction unknown, pass pointer unchanged;
41    _CLICK_IOR[S]: data of specified size sent from kernel to user;
42    _CLICK_IOW[S]: data of specified size sent from user to kernel;
43    _CLICK_IOWR[S]: data of specified size transferred in both directions. */
44 
45 /* "Non-safe" LLRPCs will not be performed in parallel with other LLRPCs or
46    handlers.  They will also block the router threads. */
47 #define _CLICK_IOX(d, n, sz)	((d) | ((sz) << 16) | (n))
48 #define _CLICK_IO(n)		_CLICK_IOX(_CLICK_IOC_VOID, (n), 0)
49 #define _CLICK_IOR(n, sz)	_CLICK_IOX(_CLICK_IOC_OUT, (n), (sz))
50 #define _CLICK_IOW(n, sz)	_CLICK_IOX(_CLICK_IOC_IN, (n), (sz))
51 #define _CLICK_IOWR(n, sz)	_CLICK_IOX(_CLICK_IOC_IN|_CLICK_IOC_OUT, (n), (sz))
52 
53 /* "Safe" LLRPCs may be performed in parallel with read handlers and other
54    safe LLRPCs, but not with write handlers or unsafe LLRPCs.  They will not
55    block the router threads. */
56 #define _CLICK_IOS(n)		_CLICK_IOX(_CLICK_IOC_VOID|_CLICK_IOC_SAFE, (n), 0)
57 #define _CLICK_IORS(n, sz)	_CLICK_IOX(_CLICK_IOC_OUT|_CLICK_IOC_SAFE, (n), (sz))
58 #define _CLICK_IOWS(n, sz)	_CLICK_IOX(_CLICK_IOC_IN|_CLICK_IOC_SAFE, (n), (sz))
59 #define _CLICK_IOWRS(n, sz)	_CLICK_IOX(_CLICK_IOC_IN|_CLICK_IOC_OUT|_CLICK_IOC_SAFE, (n), (sz))
60 
61 /* "Flat" LLRPCs do not contain pointers -- all data read or written is
62    contained in the size. They can be safe or unsafe. */
63 #define _CLICK_IORF(n, sz)	_CLICK_IOX(_CLICK_IOC_OUT|_CLICK_IOC_FLAT, (n), (sz))
64 #define _CLICK_IOWF(n, sz)	_CLICK_IOX(_CLICK_IOC_IN|_CLICK_IOC_FLAT, (n), (sz))
65 #define _CLICK_IOWRF(n, sz)	_CLICK_IOX(_CLICK_IOC_IN|_CLICK_IOC_OUT|_CLICK_IOC_FLAT, (n), (sz))
66 #define _CLICK_IORSF(n, sz)	_CLICK_IOX(_CLICK_IOC_OUT|_CLICK_IOC_SAFE|_CLICK_IOC_FLAT, (n), (sz))
67 #define _CLICK_IOWSF(n, sz)	_CLICK_IOX(_CLICK_IOC_IN|_CLICK_IOC_SAFE|_CLICK_IOC_FLAT, (n), (sz))
68 #define _CLICK_IOWRSF(n, sz)	_CLICK_IOX(_CLICK_IOC_IN|_CLICK_IOC_OUT|_CLICK_IOC_SAFE|_CLICK_IOC_FLAT, (n), (sz))
69 
70 #define CLICK_LLRPC_PROXY			_CLICK_IO(0)
71 #define CLICK_LLRPC_GET_RATE			_CLICK_IOWRSF(1, 4)
72 #define CLICK_LLRPC_GET_RATES			_CLICK_IOS(2)
73 #define CLICK_LLRPC_GET_COUNT			_CLICK_IOWRSF(3, 4)
74 #define CLICK_LLRPC_GET_COUNTS			_CLICK_IOS(4)
75 #define CLICK_LLRPC_GET_SWITCH			_CLICK_IORSF(5, 4)
76 #define CLICK_LLRPC_SET_SWITCH			_CLICK_IOWF(6, 4)
77 #define CLICK_LLRPC_MAP_IPADDRESS		_CLICK_IOWRF(7, 4)
78 #define CLICK_LLRPC_IPREWRITER_MAP_TCP		_CLICK_IOWRF(8, 12)
79 #define CLICK_LLRPC_IPREWRITER_MAP_UDP		_CLICK_IOWRF(9, 12)
80 #define CLICK_LLRPC_IPRATEMON_LEVEL_FWD_AVG	_CLICK_IO(10)
81 #define CLICK_LLRPC_IPRATEMON_LEVEL_REV_AVG	_CLICK_IO(11)
82 #define CLICK_LLRPC_IPRATEMON_FWD_N_REV_AVG	_CLICK_IO(12)
83 #define CLICK_LLRPC_IPRATEMON_SET_ANNO_LEVEL	_CLICK_IO(13)
84 #define CLICK_IOC_TOUSERDEVICE_GET_MULTI	_CLICK_IOS(15)
85 #define CLICK_IOC_TOUSERDEVICE_SET_MULTI	_CLICK_IOS(16)
86 #define CLICK_LLRPC_RAW_HANDLER			_CLICK_IOS(17)
87 #define CLICK_LLRPC_ABANDON_HANDLER		_CLICK_IOS(18)
88 #define CLICK_LLRPC_CALL_HANDLER		_CLICK_IO(19)
89 
90 struct click_llrpc_proxy_st {
91     void* proxied_handler;	/* const Router::Handler* */
92     uint32_t proxied_command;
93     void* proxied_data;
94 };
95 
96 #define CLICK_LLRPC_COUNTS_SIZE 8
97 struct click_llrpc_counts_st {
98     uint32_t n;
99     uint32_t keys[CLICK_LLRPC_COUNTS_SIZE];
100     uint32_t values[CLICK_LLRPC_COUNTS_SIZE];
101 };
102 
103 #define CLICK_LLRPC_CALL_HANDLER_FLAG_RAW 1
104 struct click_llrpc_call_handler_st {
105     int flags;
106     size_t errorlen;
107     void *errorbuf;
108 };
109 
110 /* data manipulation */
111 
112 #if CLICK_USERLEVEL || CLICK_MINIOS
113 
114 # define CLICK_LLRPC_GET_DATA(local, remote, size) (memcpy(local, remote, size), 0)
115 # define CLICK_LLRPC_PUT_DATA(remote, local, size) (memcpy(remote, local, size), 0)
116 # define CLICK_LLRPC_GET(local_obj, remote_addr) (memcpy(&(local_obj), remote_addr, sizeof(local_obj)), 0)
117 # define CLICK_LLRPC_PUT(remote_addr, local_obj) (memcpy(remote_addr, &(local_obj), sizeof(local_obj)), 0)
118 
119 #elif CLICK_LINUXMODULE
120 
121 # ifdef __cplusplus
122 #  define __CLICK_LLRPC_CAST(x) reinterpret_cast< x >
123 # else
124 #  define __CLICK_LLRPC_CAST(x) (x)
125 # endif
126 
127 # define __CLICK_LLRPC_GENERIC_GET_DATA(local, remote, size) \
128 		(copy_from_user(local, remote, size) > 0 ? -EFAULT : 0)
129 # define __CLICK_LLRPC_CONSTANT_GET_DATA(local, remote, size) \
130 		(size == 1 ? get_user(*__CLICK_LLRPC_CAST(unsigned char *)(local), __CLICK_LLRPC_CAST(unsigned char *)(remote)) \
131 		 : (size == 2 ? get_user(*__CLICK_LLRPC_CAST(unsigned short *)(local), __CLICK_LLRPC_CAST(unsigned short *)(remote)) \
132 		    : (size == 4 ? get_user(*__CLICK_LLRPC_CAST(unsigned *)(local), __CLICK_LLRPC_CAST(unsigned *)(remote)) \
133 		       : __CLICK_LLRPC_GENERIC_GET_DATA(local, remote, size))))
134 
135 # define __CLICK_LLRPC_GENERIC_PUT_DATA(remote, local, size) \
136 		(copy_to_user(remote, local, size) > 0 ? -EFAULT : 0)
137 # define __CLICK_LLRPC_CONSTANT_PUT_DATA(remote, local, size) \
138 		(size == 1 ? put_user(*__CLICK_LLRPC_CAST(const unsigned char *)(local), __CLICK_LLRPC_CAST(unsigned char *)(remote)) \
139 		 : (size == 2 ? put_user(*__CLICK_LLRPC_CAST(const unsigned short *)(local), __CLICK_LLRPC_CAST(unsigned short *)(remote)) \
140 		    : (size == 4 ? put_user(*__CLICK_LLRPC_CAST(const unsigned *)(local), __CLICK_LLRPC_CAST(unsigned *)(remote)) \
141 		       : __CLICK_LLRPC_GENERIC_PUT_DATA(remote, local, size))))
142 
143 # define CLICK_LLRPC_GET_DATA(local, remote, size) \
144 		(__builtin_constant_p(size) && size <= 4 \
145 		 ? __CLICK_LLRPC_CONSTANT_GET_DATA(local, remote, size) \
146 		 : __CLICK_LLRPC_GENERIC_GET_DATA(local, remote, size))
147 # define CLICK_LLRPC_PUT_DATA(remote, local, size) \
148 		(__builtin_constant_p(size) && size <= 4 \
149 		 ? __CLICK_LLRPC_CONSTANT_PUT_DATA(remote, local, size) \
150 		 : __CLICK_LLRPC_GENERIC_PUT_DATA(remote, local, size))
151 
152 # define CLICK_LLRPC_GET(local_obj, remote_addr) \
153 		get_user((local_obj), (remote_addr))
154 # define CLICK_LLRPC_PUT(remote_addr, local_obj) \
155 		put_user((local_obj), (remote_addr))
156 
157 #elif CLICK_BSDMODULE
158 
159 /*
160  * XXX  LLRPC isn't implemented for BSD yet.
161  */
162 
163 # define CLICK_LLRPC_GET_DATA(local, remote, size) ((void)(local), (void)(remote), (void)(size), -EFAULT)
164 # define CLICK_LLRPC_PUT_DATA(remote, local, size) ((void)(local), (void)(remote), (void)(size), -EFAULT)
165 # define CLICK_LLRPC_GET(local_obj, remote_addr) ((void)(local_obj), (void)(remote_addr), -EFAULT)
166 # define CLICK_LLRPC_PUT(remote_addr, local_obj) ((void)(local_obj), (void)(remote_addr), -EFAULT)
167 
168 #endif
169 
170 /* CLICK_NTOH_LLRPC: portable LLRPC numbers to host LLRPC numbers */
171 /* CLICK_HTON_LLRPC: host LLRPC numbers to portable LLRPC numbers */
172 /* both macros are only suitable for integer constants and the like */
173 #if _CLICK_IOC_VOID != _CLICK_NET_IOC_VOID || _CLICK_IOC_OUT != _CLICK_NET_IOC_OUT || _CLICK_IOC_IN != _CLICK_NET_IOC_IN
174 # define CLICK_LLRPC_NTOH(command) \
175 	(((command) & _CLICK_NET_IOC_VOID ? _CLICK_IOC_VOID : 0) \
176 	 | ((command) & _CLICK_NET_IOC_OUT ? _CLICK_IOC_OUT : 0) \
177 	 | ((command) & _CLICK_NET_IOC_IN ? _CLICK_IOC_IN : 0) \
178 	 | ((command) & _CLICK_IOC_BASE_MASK))
179 # define CLICK_LLRPC_HTON(command) \
180 	(((command) & _CLICK_IOC_VOID ? _CLICK_NET_IOC_VOID : 0) \
181 	 | ((command) & _CLICK_IOC_OUT ? _CLICK_NET_IOC_OUT : 0) \
182 	 | ((command) & _CLICK_IOC_IN ? _CLICK_NET_IOC_IN : 0) \
183 	 | ((command) & _CLICK_IOC_BASE_MASK))
184 #else
185 # define CLICK_LLRPC_NTOH(command) (command)
186 # define CLICK_LLRPC_HTON(command) (command)
187 #endif
188 
189 /* sanity checks */
190 #ifdef __FreeBSD__
191 # if _CLICK_IOC_VOID != IOC_VOID || _CLICK_IOC_OUT != IOC_OUT || _CLICK_IOC_IN != IOC_IN
192 #  error "bad _CLICK_IOC constants"
193 # endif
194 #endif
195 #endif
196