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