1# Cjdns Admin API 2 3Cjdns is inspected and configured through a UDP socket. 4When cjdroute starts up, it reads the configuration file and spawns cjdns core. The core 5knows nothing but the port which it should bind to and the private key which it should use. 6All other information such as peers, interfaces and passwords is given to the core through the 7admin UDP interface. When cjdroute is finished setting up the core, it exits leaving the core 8running in the background. 9 10You can call all of the functions which are called by cjdroute to collect information and alter 11the core's configuration. 12 13## How a function works 14To call a function you send a UDP packet containing a bencoded request to the core and it sends 15back a bencoded response. 16 17 echo -n 'd1:q4:pinge' | nc6 -u -t 1 -n -w3 127.0.0.1 11234 18 19If you are more comfortable writing json then benc, you can use benc2json in reverse mode to 20preprocess your message. **Note**: benc2json has been removed in 2821c81d49 to speed up the build. 21 22 echo '{ "q": "ping" }' | ./build/benc2json -r 23 24Stream the request from json into benc and then make the request to the core: 25 26 echo '{ "q": "ping" }' \ 27 | ./build/benc2json -r \ 28 | tr -d '\n' \ 29 | nc6 -u -t 1 -n -w3 127.0.0.1 11234 30 31Get the result back into json: 32 33 echo '{ "q": "ping" }' \ 34 | ./build/benc2json -r \ 35 | tr -d '\n' \ 36 | nc6 -u -t 1 -n -w3 127.0.0.1 11234 \ 37 | ./build/benc2json 38 39 40## Transaction ID 41Because you can send multiple messages at once, you may add a transaction ID to a message and it 42will be reflected back to you in the response. 43 44 echo '{ "q": "ping", "txid": "my request" }' \ 45 | ./build/benc2json -r \ 46 | tr -d '\n' \ 47 | nc6 -u -t 1 -n -w3 127.0.0.1 11234 \ 48 | ./build/benc2json 49 50Result: 51 52 { 53 "txid" : "my request", 54 "q" : "pong" 55 } 56 57 58## Arguments 59Some functions require arguments and others allow arguments but assume defaults if they are 60not provided. Arguments are sent to a function through a benc *dictionary* called `args`. 61 62The `Admin_availableFunctions()` function has an optional argument called `page`, this is 63because there are too many functions to be described in a single UDP packet. The following 64command will get the first page of functions from `Admin_availableFunctions` which will 65describe other functions and their required and allowed arguments. 66 67 echo -n ' 68 { 69 "q": "Admin_availableFunctions", 70 "args": { 71 "page": 0 72 } 73 }' | ./build/benc2json -r \ 74 | tr -d '\n' \ 75 | nc6 -u -t 1 -n -w3 127.0.0.1 11234 \ 76 | ./build/benc2json 77 78 79## Authentication 80Any function which changes the state of cjdns core requires authentication to carry out. 81Authentication is done on a per-request basis. Functions which don't require authentication 82can still be called with authentication and will still fail if the authentication is incorrect. 83 84* Step 1: Request a cookie from the server. 85 86* Step 2: Calculate the SHA-256 of your admin password and the cookie, place this hash and cookie 87in the request. 88 89* Step 3: Calculate the SHA-256 of the entire request with the hash and cookie added, 90replace the hash in the request with this result. 91 92Steps 1 and 2 securely bind the password to the cookie so that the password hash cannot 93be taken and used again in another request later on, step 3 binds the password and cookie to 94the request so that a man-in-the-middle cannot change the content of the request in flight. 95 96 97### Anatomy of an authenticated request 98 99A plain request such as `{"q": "ping"}` becomes `{"q":"auth", "aq":"ping", "hash":<calculated hash>}`. 100The `q` field is moved to `aq` (authenticated query) and the `q` field says `auth`. 101 102**NOTE:** A cookie is only valid for 10 seconds so requesting and using a cookie must be done 103in the same script. 104 105**NOTE2:** Cookies are reusable *for now* this is not part of the API and is considered a 106bug, you should always request a new cookie for each authenticated request otherwise you may 107be broke by changes in the future. 108 109### By example 110 111**Step 1:** Get the cookie 112 113 RESP=`echo -n 'd1:q6:cookiee' | nc6 -u -t 1 -n -w3 127.0.0.1 11234` \ 114 echo response=${RESP}; \ 115 COOKIE=`echo ${RESP} | sed 's/d6:cookie10:\([0-9]*\)e/\1/'` \ 116 echo cookie=${COOKIE}; 117 118**Step 2:** Calculate the hash of the password and cookie: 119For this step, you will need the admin password from your cjdroute.conf file, it's to be found 120inside of the block which says `"admin": {`. 121 122 ADMIN_PASS=you_will_find_this_in_your_cjdroute_dot_conf \ 123 REQUEST='{"q": "auth", "aq": "ping", "hash": "__HASH__", "cookie": "__COOKIE__"}' \ 124 COOKIE_RESP=`echo -n 'd1:q6:cookiee' | nc6 -u -t 1 -n -w3 127.0.0.1 11234` \ 125 COOKIE=`echo ${COOKIE_RESP} | sed 's/d6:cookie10:\([0-9]*\)e/\1/'` \ 126 HASH_ONE=`echo -n "${ADMIN_PASS}${COOKIE}" | sha256sum -b | cut -d\ -f1` ; \ 127 REQ_ONE=`echo $REQUEST | sed -e "s/__HASH__/${HASH_ONE}/" -e "s/__COOKIE__/${COOKIE}/" \ 128 | ./build/benc2json -r | tr -d '\n'` ; \ 129 echo "hash of password and cookie is ${HASH_ONE}" ; \ 130 echo "Request with cookie and hash added:" ; \ 131 echo "${REQ_ONE}" ; \ 132 echo "JSON version of request:" ; \ 133 echo "${REQ_ONE}" | ./build/benc2json 134 135**Step 3:** Calculate the SHA-256 of the entire request and replace the one in the request: 136This will calculate the final request and send it to cjdns. 137 138 ADMIN_PASS=you_will_find_this_in_your_cjdroute_dot_conf \ 139 REQUEST='{"q": "auth", "aq": "ping", "hash": "__HASH__", "cookie": "__COOKIE__"}' \ 140 COOKIE_RESP=`echo -n 'd1:q6:cookiee' | nc6 -u -t 1 -n -w3 127.0.0.1 11234` \ 141 COOKIE=`echo ${COOKIE_RESP} | sed 's/d6:cookie10:\([0-9]*\)e/\1/'` \ 142 HASH_ONE=`echo -n "${ADMIN_PASS}${COOKIE}" | sha256sum -b | cut -d\ -f1` \ 143 REQ_ONE=`echo $REQUEST | sed -e "s/__HASH__/${HASH_ONE}/" -e "s/__COOKIE__/${COOKIE}/" \ 144 | ./build/benc2json -r | tr -d '\n'` \ 145 FINAL_HASH=`echo -n "$REQ_ONE" | sha256sum -b | cut -d\ -f1` \ 146 FINAL_REQ=`echo $REQ_ONE | sed -e "s/${HASH_ONE}/${FINAL_HASH}/"` ; \ 147 echo -n "$FINAL_REQ" \ 148 | nc6 -u -t 1 -n -w3 127.0.0.1 11234 \ 149 | ./build/benc2json 150 151 152If you see this: 153 154 { 155 "q" : "pong" 156 } 157 158then it has succeeded, if the password is incorrect, you will see this: 159 160 { 161 "error" : "Auth failed." 162 } 163 164### Tools: 165 166Obviously using bash to craft cjdns admin RPC calls is probably the most awkward way possible, 167there are tools in cjdns/contrib which will help you craft requests, specifically there are 168libraries written in python and perl which will allow users to call cjdns internal functions 169as python/perl native functions. A tool called `cexec` is provided with the python library which 170allows you to call cjdns functions from shell scripts or the command line as follows: 171 172 ./contrib/python/cexec 'ping()' 173 174 175## Cjdns Functions: 176 177 user@ubnta8:~/wrk/cjdns$ ./contrib/python/cexec 'functions()' | sort 178 Admin_asyncEnabled() 179 Admin_availableFunctions(page='') 180 Allocator_bytesAllocated() 181 Allocator_snapshot(includeAllocations='') 182 AuthorizedPasswords_add(password, user, authType='', ipv6=0) 183 AuthorizedPasswords_list() 184 AuthorizedPasswords_remove(user) 185 Core_exit() 186 Core_initTunnel(desiredTunName=0) 187 Core_pid() 188 ETHInterface_beacon(interfaceNumber='', state='') 189 ETHInterface_beginConnection(publicKey, macAddress, interfaceNumber='', password=0) 190 ETHInterface_new(bindDevice) 191 InterfaceController_disconnectPeer(pubkey) 192 InterfaceController_peerStats(page='') 193 IpTunnel_allowConnection(publicKeyOfAuthorizedNode, ip6Address=0, ip4Address=0) 194 IpTunnel_connectTo(publicKeyOfNodeToConnectTo) 195 IpTunnel_listConnections() 196 IpTunnel_removeConnection(connection) 197 IpTunnel_showConnection(connection) 198 memory() 199 NodeStore_dumpTable(page) 200 NodeStore_getLink(parent, linkNum) 201 NodeStore_getRouteLabel(pathParentToChild, pathToParent) 202 NodeStore_nodeForAddr(ip=0) 203 ping() 204 RainflyClient_addKey(ident) 205 RainflyClient_addServer(addr) 206 RainflyClient_minSignatures(count) 207 RouterModule_findNode(nodeToQuery, target, timeout='') 208 RouterModule_getPeers(path, nearbyPath=0, timeout='') 209 RouterModule_lookup(address) 210 RouterModule_pingNode(path, timeout='') 211 SearchRunner_showActiveSearch(number) 212 Security_checkPermissions() 213 Security_dropPermissions() 214 Security_setUser(user) 215 SessionManager_getHandles(page='') 216 SessionManager_sessionStats(handle) 217 SwitchPinger_ping(path, data=0, keyPing='', timeout='') 218 UDPInterface_beginConnection(publicKey, address, interfaceNumber='', password=0) 219 UDPInterface_new(bindAddress=0) 220 221 222### RouterModule_pingNode() 223 224**Auth Required** 225 226Send a node a cjdns ping request. 227 228Parameters: 229 230* required String **path** may be a route such as "0000.0000.0000.1d53" or an ip address such as 231"fc5d:baa5:61fc:6ffd:9554:67f0:e290:7536", or an ip with explicit path 232eg: "fc5d:baa5:61fc:6ffd:9554:67f0:e290:7536@0000.0000.0000.1d53" 233 234* Int **timeout** (optional) the number of milliseconds after which to timeout the ping 235if there is no response. Defaults to router's adaptive ping timeout if unspecified. 236 237Responses: 238 239* **error**: `could not find node to ping` if there was no node by the given address found in the 240routing table 241 242* **result**: `timeout` gives timeout and number of milliseconds since the ping. 243 244* **result**: `pong` gives `version` representing the git hash of the source code which built the 245pinged node, and `ms` which is the number of milliseconds since the original ping. 246 247Examples: 248 249 >>> cjdns.RouterModule_pingNode('fc38:4c2c:1a8f:3981:f2e7:c2b9:6870:6e84') 250 {'version': '5c5e84ccdba3f31f7c88077729700b4368320bc2', 'result': 'pong', 'ms': 79} 251 252 >>> cjdns.RouterModule_pingNode('fc5d:baa5:61fc:6ffd:9554:67f0:e290:7536') 253 {'error': 'could not find node to ping'} 254 255 >>> cjdns.RouterModule_pingNode('0000.0000.0000.0013') 256 {'version': '2b62b9ae911f1044e45f3f28fdd63d0d5a7fc512', 'result': 'pong', 'ms': 0} 257 258 >>> cjdns.RouterModule_pingNode('a') 259 {'error': "Unexpected length, must be either 39 char ipv6 address (with leading zeros) 260 eg: 'fc4f:000d:e499:8f5b:c49f:6e6b:01ae:3120' or 19 char path eg: '0123.4567.89ab.cdef'"} 261 262 >>> cjdns.RouterModule_pingNode('aaaaaaaaaaaaaaaaaaa') 263 {'error': 'parse path failed'} 264 265 >>> cjdns.RouterModule_pingNode('aaaaaaaaaaaaaaaaaaazzzzzzzzzzzzzzzzzzzz') 266 {'error': 'parsing address failed'} 267 268 >>> cjdns.RouterModule_pingNode('fc38:4c2c:1a8f:3981:f2e7:c2b9:6870:6e84', 10) 269 {'result': 'timeout', 'ms': 10} 270 271### ETHInterface Functions: 272 273ETHInterface is a connector which allows cjdns nodes on the same lan to automatically connect 274without the need to IP addresses on the LAN or sharing of connection credentials. It works on 275wireless LANs as well as wired Ethernet LANs. 276 277#### ETHInterface_new() 278 279Create a new ETHInterface and bind it to a device. 280**NOTE**: this call will always fail with `'error': 'call to socket() failed. [permission denied]'` 281unless it is running as root and will fail with `process cannot open more files` if 282`Security_setUser()` has already been called. 283 284**Auth Required** 285 286Parameters: 287 288* required String **bindDevice** the name of the Ethernet device to bind to, eg: `eth0` or `wlan0`. 289 290Returns: 291 292* Int **interfaceNumber** an number which can be used to carry out other operations on the interface later. 293 294 295#### ETHInterface_beginConnection() 296 297Connect an ETHInterface to another computer which has an ETHInterface running. 298 299**Auth Required** 300 301Parameters: 302 303* required String **publicKey** The public key of the other node, similar to `UDPInterface_beginConnection()` 304* required String **macAddress** The mac address of the other node. 305* Int **interfaceNumber** The interface number to use, assumed 0 (first ETHinterface created) if not supplied. 306* String **password** A password for connecting to the other node if required. 307 308Returns: 309 310* String **error**: `none` if everything went well. 311 312Other errors are self-explanitory. 313 314 315#### ETHInterface_beacon() 316 317Enable or disable sending or receiving of ETHInterface beacon messages. 318ETHInterface uses periodic beacon messages to automatically peer nodes which are on the same LAN. 319Be mindful that if your LAN has is open wifi, enabling beaconing will allow anyone to peer with you. 320 321**Auth Required** 322 323Beacon States: 3240. Disabled, no beacons are sent and incoming beacon messages are discarded. 3251. Accepting, no beacons are sent but if an incoming beacon is received, it is acted upon. 3262. Sending and Accepting, beacons are sent and accepted. 327 328Parameters: 329 330* Int **interfaceNumber** The number of the ETHInterface to change the state of, assumed 0 if not provided. 331* Int **state** What state to switch to, if not provided, the current state will be queried only. 332 333Returns: 334 335* String **error**: `none` if all went well. 336* Int **state**: the state number after the call is complete. 337* String **stateName**: a description of the state. 338 339 340Example: 341 342 $ ./contrib/python/cexec 'ETHInterface_beacon(2)' 343 {'txid': 'FYRKHAPIM3', 'error': 'invalid interfaceNumber'} 344 345 $ ./contrib/python/cexec 'ETHInterface_beacon(0)' 346 {'txid': 'Z7KHE7SZ5R', 'state': 2, 'stateName': 'sending and accepting', 'error': 'none'} 347 348 $ ./contrib/python/cexec 'ETHInterface_beacon(0, 0)' 349 {'txid': 'TP1R8PYCNS', 'state': 0, 'stateName': 'disabled', 'error': 'none'} 350 351 $ ./contrib/python/cexec 'ETHInterface_beacon(0, 1)' 352 {'txid': 'UGKKGX4ZC9', 'state': 1, 'stateName': 'accepting', 'error': 'none'} 353 354 $ ./contrib/python/cexec 'ETHInterface_beacon(0, 2)' 355 {'txid': '1B7RXJEH3N', 'state': 2, 'stateName': 'sending and accepting', 'error': 'none'} 356 357 358### IpTunnel Functions 359 360IPTunnel is designed to allow tunneling of IPv4 and IPv6 packets through a cjdns network 361to the external internet or to a virtual LAN. It provides familiar VPN type functionality. 362There are 2 nodes, a client and a server, the server uses `IPTunnel_allowConnection()` and the 363client uses `IPTunnel_connectTo()` the server assigns IPv4 and/or IPv6 addresses to the client 364and the client is required to use only these addresses, subnet assignment is not supported. 365When the client uses `IPTunnel_connectTo()`, it sends a request to the server for addresses and 366continues polling the server periodically until the addresses are provided. 367 368#### IpTunnel_listConnections() 369 370List the connection numbers of all IPTunnel connections. 371 372**Auth Required** 373 374Returns: 375 376* List **connections**: A list of integers representing the connection numbers for each connection. 377* String **error**: `none` 378 379 380Example: 381 382 $ ./contrib/python/cexec 'IpTunnel_listConnections()' 383 {'connections': [0], 'txid': '5ZFPFJ60AT', 'error': 'none'} 384 385 386#### IpTunnel_showConnection() 387 388Show information about a perticular IPTunnel connection. 389 390**Auth Required** 391 392Parameters: 393 394* required Int **connection**: the connection number for the connection to show information about. 395 396Returns: 397 398* Int **outgoing**: 1 if the connection is outgoing, 0 if it's incoming. 399* String **key**: the cjdns public key of the foreign node. 400* String **ip6Address**: the IPv6 address which is assigned to this IPTunnel if applicable. 401* Int **ip6Prefix**: the IPv6 netmask/prefix length which is assigned to this IPTunnel if applicable. 402* String **ip4Address**: the IPv4 address which is assigned to this IPTunnel if applicable. 403* Int **ip4Prefix**: the IPv4 netmask/prefix length which is assigned to this IPTunnel if applicable. 404* String **error**: `none` unless the connection number is invalid. 405 406Examples: 407 408 # Prior to getting it's addresses from the server, they are not listed. 409 $ ./contrib/python/cexec 'IpTunnel_showConnection(0)' 410 {'outgoing': 1, 'txid': 'REIV40SXD9', 'key': 'd5d0wu0usrkufd8s98t19gt7m2ggvbz1xbnuxu82x63uqlnk2kb0.k', 'error': 'none'} 411 412 # After a short wait, the addresses are provided and they are now listed. 413 $ ./contrib/python/cexec 'IpTunnel_showConnection(0)' 414 {'outgoing': 1, 'txid': 'CAQCTWECRD', 'ip4Address': '192.168.10.2', 'key': 'd5d0wu0usrkufd8s98t19gt7m2ggvbz1xbnuxu82x63uqlnk2kb0.k', 'error': 'none', 'ip6Address': '2a02:2498:e000:20::144:3'} 415 416 417#### IpTunnel_removeConnection() 418 419Remove an IPTunnel connection from the list, the other end will no longer be able to send traffic 420over this connection. 421 422**Auth Required** 423 424**NOT IMPLEMENTED** 425 426 427#### IpTunnel_connectTo() 428 429Initiate an *outgoing* connection to another node and request IP addresses from them. 430 431**Auth Required** 432 433Parameters: 434 435* required String **publicKeyOfNodeToConnectTo** the pubkey of the node to connect to. 436 437Returns: 438 439* String **error**: `none` if all went well 440* Int **connection**: the connection number of the new connection 441 442Examples: 443 444 $ ./contrib/python/cexec 'IpTunnel_connectTo("d5d0wu0usrkufd8s98t19gt7m2ggvbz1xbnuxu82x63uqlnk2kb0.k")' 445 {'connection': 1, 'txid': '9QXRQO1FG8', 'error': 'none'} 446 447 448#### IpTunnel_allowConnection() 449 450Allow in *incoming* connection from another node, they must also use `IPTunnel_connectTo()` in order 451to complete the connection. 452 453**Auth Required** 454 455Parameters: 456* required String **publicKeyOfAuthorizedNode** The key of the node which is authorized to connect. 457* String **ip6Address** The IPv6 address to give them if applicable. 458* String **ip4Address** The IPv4 address to give them if applicable. 459 460Returns: 461 462* String **error** `none` if all went well. 463* Int **connection** the connection number for the new connection. 464 465 466 467### UDPInterface Functions 468 469UDPInterface is the basic cjdns interface which is used to link distant nodes over the internet. 470It will work on a LAN as long as the nodes have IP addresses but for linking on a LAN, ETHInterface 471is easier. 472 473#### UDPInterface_new() 474 475Create a new UDPInterface which is either bound to an address/port or not. 476 477**NOTE**: This call will fail with `'error': 'call to socket() failed [process cannot open more files]'` 478is `Security_noFiles()` has already been called. 479 480Parameters: 481 482* String **bindAddress**: the address/port to bind to, if unspecified, it is assumed to be `0.0.0.0`. 483 484Returns: 485 486* String **error** `none` if all went well 487* Int **interfaceNumber** the number of the interface, usable with `UDPInterface_beginConnection()` 488 489 490#### UDPInterface_beginConnection() 491 492Start a direct connection to another node. 493 494**Auth Required** 495 496Parameters: 497 498* required String **publicKey** the base32 public key for the node to connect to, ending in .k. 499* required String **address** the ip address and port for the node, at this time DNS resolution 500and IPv6 is not supported. 501* Int **interfaceNumber** the number for the UDPInterface to use for connecting, provided by 502*UDPInterface_new()* if not sent, 0 is assumed. 503* String **password** a password to use when connecting. 504 505Note: just because it returns `'error': 'none'` does not mean that the connection was successful. 506The neighbor may still reject our connection attempts. 507 508Example: 509 510 >>> cjdns.UDPInterface_beginConnection("v0zyvrjuc4xbzh4n9c4k3qpx7kg8xgndv2k45j9nfgb373m8sss0.k", "192.168.0.2:10000", "null") 511 {'error': 'none'} 512 513 >>> cjdns.UDPInterface_beginConnection("v0zyvrjuc4xbzh4n9c4k3qpx7kg8xgndv2k45j9nfgb373m8sss0.k", "x", "null") 514 {'error': 'unable to parse ip address and port.'} 515 516 >>> cjdns.UDPInterface_beginConnection("k", "x", "null") 517 {'error': 'publicKey is too short, must be 52 characters long.'} 518 519 >>> cjdns.UDPInterface_beginConnection("------------------------------------------------------", "x", "null") 520 {'error': 'failed to parse publicKey.'} 521 522 >>> cjdns.UDPInterface_beginConnection("zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz0.k", "192.168.0.2:10000", "null") 523 {'error': 'invalid cjdns public key.'} 524 525 >>> cjdns.UDPInterface_beginConnection("v0zyvrjuc4xbzh4n9c4k3qpx7kg8xgndv2k45j9nfgb373m8sss0.k", "[1234::5]:10000", "null") 526 {'error': 'different address type than this socket is bound to.'} 527 528 529### AdminLog Functions: 530 531Since cjdns contains so many logging locations, logging to a file would not only be inefficient 532but it would fill up your disk rather quickly. Because of this, cjdns logging is only enabled on 533request, with these functions you can ask for logs to be enabled on a log level, per-file or even 534per-line basis. 535 536Log levels may be excluded at compile time in which case they will not be available. 537Each log level implies inclusion of every higher level, if you subscribe to **INFO** logging, you 538will also automatically get **WARN**, **ERROR**, and **CRITICAL**. 539 540Cjdns log levels: 541 542* **KEYS** Not compiled in by default, contains private keys and other secret information. 543* **DEBUG** Default level, contains lots of information which is probably not useful unless you are 544diagnosing an ongoing problem. 545* **INFO** Shows starting and stopping of various components and general purpose information. 546* **WARN** Generally this means some system has undergone a minor failure, this includes failures 547due to network disturbance. 548* **ERROR** This means there was a (possibly temporary) failure of a system within cjdns. 549* **CRITICAL** This means something is broken such that the cjdns core will likely 550have to exit immedietly. 551 552 553To see an implementation of cjdns log consumer, look at `contrib/python/cjdnslog`. 554 555 556#### AdminLog_subscribe() 557 558Subscribe to logging of a level/file/line. 559 560**Auth Required** 561 562**NOTE**: Because this function responds asynchronously, using `netcat` or `cexec` to call it 563will not work, additionally it will stop sending asynchronous messages unless an incoming message 564comes in every 10 seconds so you must send periodic messages on the same UDP port. 565See: `Admin_asyncEnabled()` for more information. 566 567Parameters: 568 569* Int **line**: If specified, the logging will be constrained to the log message which appers on 570the given line number in the source file. 571* String **file**: If specified, the logging will be constrained to the named file, names are not 572fully qualified, use "CryptoAuth.c", not "/path/to/CryptoAuth.c". 573* String **level**: If specified, the logging will be constrained to log lines which are of the 574given level or higher. 575 576Returns: 577 578* String **error**: `none` if all goes well. 579* String **streamId**: an opaque string which will be contained in each log message. 580 581Log message structure: 582 583* String **file** the name of the file where the log message came from, eg: "CryptoAuth.c". 584* String **level** the log level, one of `["KEYS", "DEBUG", "INFO", "WARN", "ERROR", "CRITICAL"]` 585* Int **line** the line number of the line where the log function was called. 586* String **message** the log message 587* String **streamId** the streamId for the logging subscription. 588* Int **time** the time in seconds since the unix epoch when the log message was created. 589* String **txid** the same transaction which was used in the call to `AdminLog_subscribe()`. 590 591 592#### AdminLog_unsubscribe() 593 594Unsubscribe from logging. 595 596**Auth Required** 597 598Parameters: 599 600* required String **streamId**: The id returned in the call to `AdminLog_subscribe()`. 601 602Returns: 603 604* String **error**: `none` if the subscription existed and was removed. 605 606**Note**: If the subscription has already timed out, removing it will yield `'error': 'No such subscription.'`. 607 608Example: 609 610 $ ./contrib/python/cexec 'AdminLog_subscribe()' 611 {'txid': '0EKWEP7VXI', 'streamId': 'f1a0e225183397f4', 'error': 'none'} 612 613 $ ./contrib/python/cexec 'AdminLog_unsubscribe("f1a0e225183397f4")' 614 {'txid': 'CB4V7KLYCC', 'error': 'none'} 615 616 617### Admin Functions 618 619These functions are for dealing with the Admin interface, the infrastructure which allows all 620of the other functions throughout cjdns to be accessed from the admin socket. 621 622#### Admin_availableFunctions() 623 624Get a list of functions which are available to the admin socket as well as their required and 625optional parameters, unfortunately their return values are not provided and can only be determined 626by experimentation or by reading the source. 627 628**Note**: The list of functions is paged to make sure each message fits inside of a UDP packet, in 629order to get the whole list of functions, you must increment the `page` parameter until the result 630no longer contains the `more` field. 631 632Parameters: 633 634* Int **page**: the page of functions to request, if unspecified it will be assumed to be 0. 635 636Returns: 637 638* Dict **availableFunctions**: a map of function descriptions by function name. 639* Int **more**: only present if there are more pages. 640 641##### Function Description: 642 643Each function description is a Dict of function parameters with the parameter name as the key and 644the specifications as the value. The specification `required` is an Int which is either 0 meaning 645the parameter is optional or 1 meaning it is required. `type` is a String which is one of 646`["Int", "String", "Dict", "List"]` and defines the type which the parameter must be. 647 648 'AdminLog_subscribe': { 649 'line': { 650 'required': 0, 651 'type': 'Int' 652 }, 653 'file': { 654 'required': 0, 655 'type': 'String' 656 }, 657 'level': { 658 'required': 0, 659 'type': 'String' 660 } 661 } 662 663 664#### Admin_asyncEnabled() 665 666This function is for determining whether asynchronous communication is allowed. 667Asynchronous communication, EG: AdminLog responses, is only allowed with clients which satisfy 668certain requirements. 669 6701. They must send an authenticated request, in the case of AdminLog this is no worry because 671`AdminLog_subscribe()` requires authentication. 6722. They must have sent something in the past 10 seconds, because of the statelessness of UDP, 673there is no way to tell a client which is listening quietly from one which has wandered off so 674in order to remain enabled, it must periodically ping (or periodically call `Admin_asyncEnabled()`). 675These calls do not need to be authenticated, there just needs to have been one in history. 676 677Returns: 678 679* Int **asyncEnabled**: 1 if asynchronous communication is allowed for this session, 0 otherwise. 680 681Example: 682This example illustrates how using `cexec` to call it returns true because `cexec` uses 683authenticated calls whereas manually calling it without authentication returns false. 684 685 $ ./contrib/python/cexec 'Admin_asyncEnabled()' 686 {'asyncEnabled': 1, 'txid': '74GF0SS2N0'} 687 688 echo '{ "q": "Admin_asyncEnabled" }' \ 689 | ./build/benc2json -r \ 690 | tr -d '\n' \ 691 | nc -u 127.0.0.1 11234 \ 692 | ./build/benc2json 693 694 { 695 "asyncEnabled" : 0 696 } 697 698 699### Security Functions 700 701These functions are available for putting the cjdns core into a sandbox where 702a security breach within the core would be less likely to cause a total system compromize. 703 704 705#### Security_setUser() 706 707Set the user ID which cjdns is running under to a different user. This function allows cjdns 708to shed privileges after starting up. 709 710**NOTE**: This function will always fail with an error about `process cannot open more files` if 711`Security_noFiles()` has already been called. 712 713Parameters: 714 715* required String **user**: the name of the user to change to. 716 717Return: 718 719* String **error**: `none` if all went well, otherwise a description of the failure. 720 721 722#### Security_noFiles() 723 724Set the hard open file limit to zero, while this does not force closed file descriptors which are 725already open, it makes any function requiring the opening of a file to fail providing a powerful 726sandbox. By calling this function after cjdns is started, one can insure that cjdns core cannot 727touch the filesystem or open network sockets which it does not already have open. This will however 728prevent a number of other admin API functions fron working. 729 730Returns: 731 732* String **error**: `none` 733 734Examples: 735 736 $ ./contrib/python/cexec 'UDPInterface_new("[::]:2048")' 737 {'interfaceNumber': 3, 'txid': 'NQGOZXJZIC', 'error': 'none'} 738 739 $ ./contrib/python/cexec 'Security_noFiles()' 740 {'txid': 'CQYQWA5SZY', 'error': 'none'} 741 742 $ ./contrib/python/cexec 'UDPInterface_new("[::]:5000")' 743 {'txid': 'UZH9LIUOG0', 'cause': 'process cannot open more files', 'error': 'call to socket() failed [process cannot open more files]'} 744 745 746 747### Core_initTunnel() 748 749This function is used during cjdns startup to initialize the TUN device, set it's IP address 750and set the MTU, it is hastily designed and may be removed in the future. 751 752Parameters: 753 754* String **desiredTunName**: the name of the TUN device to use, if unspecified it will ask the 755kernel for a new device. 756 757Returns: 758 759* String **error**: `none` if all went well, otherwise the error which occured. 760 761**Note**: an error will be returned if anything goes wrong initializing the tunnel, setting it's 762IP address or setting it's MTU, even if there is an error, the tunnel may work just fine and 763even if the tunnel doesn't work, cjdns will function as a router only without the TUN device. 764 765 766### Core_exit() 767 768A function to stop cjdns. 769 770Returns: 771 772* String **error**: `none` before exiting. 773 774 775 776### ping() 777 778Returns: 779 780 {'q':'pong'} 781 782For checking if the admin connection is functioning. 783 784 785### RouterModule_lookup() 786 787**Auth Required** 788 789Parameters: 790 791* String **address** a 39 character (zero padded) ipv6 address. 792 793Returns: 794 795* A route if one is found in the routing table. 796* An address and route of the node which should be handed the packet, 797if a route is not found in the local table. 798* An error if the address is not parsable. 799 800Examples: 801 802 >>> print cjdns.RouterModule_lookup('fc5d:baa5:61fc:6ffd:9554:67f0:e290:7535') 803 {'result': '0000.0000.0000.1953', 'error': 'none'} 804 805 >>> print cjdns.RouterModule_lookup('fc5d:baa5:61fc:6ffd:9554:67f0:e290:7536') 806 {'result': 'fcf1:a7a8:8ec0:589b:c64c:cc95:1ced:3679@0000.0000.0000.0013', 'error': 'none'} 807 808 >>> print cjdns.RouterModule_lookup('f') 809 {'result': '', 'error': 'address wrong length'} 810 811 >>> print cjdns.RouterModule_lookup('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz') 812 {'result': '', 'error': 'failed to parse address'} 813 814 815### AuthorizedPasswords_add() 816 817**Auth Required** 818 819Parameters: 820 821* String **password** a password which will allow neighbors to make direct connections. 822* String **user** a friendly string to identify this password. 823* Int **authType** (optional) the method for authenticating, 824defaults to `1` (only currently supported method). 825 826Returns: 827 828* **error**:`none` if everything went well. 829* **error**:`Specified auth type is not supported.` if the auth type is specified and not `1`. 830* **error**:`Password already added.` if you try to add the same user or password twice. 831* **error**:`Out of memory to store password.` if the buffer for storing 832authorized passwords is full. 833 834Examples: 835 836 $ ./contrib/python/cexec 'AuthorizedPasswords_add(user="test",password="yh14wl2ffgcqq6bvut12xrz7g3")' 837 {'error': 'none'} 838 839 $ ./contrib/python/cexec 'AuthorizedPasswords_add(user="test2",password="2yh14wl2ffgcqq6bvut12xrz7g3",authType=300)' 840 {'error': 'Specified auth type is not supported.'} 841 842 $ ./contrib/python/cexec 'AuthorizedPasswords_add(user="test",password="yh14wl2ffgcqq6bvut12xrz7g3")' 843 {'error': 'Password already added.'} 844 845### AuthorizedPasswords_list() 846 847**Auth Required** 848 849Get a list of all the authorized users. 850 851Example: 852 853 $ ./contrib/python/cexec 'AuthorizedPasswords_list()' 854 {'total': 2, 'users': ['Test User1', 'Local Peers'], 'txid': 'W0DUG0D50K'} 855 856### memory() 857 858Get the number of bytes of memory allocated by all memory allocators in the router. 859 860Example: 861 862 >>> cjdns.memory() 863 {'bytes': 779259} 864 865 866### NodeStore_dumpTable() 867 868Parameters: 869 870* Int **page** the page of the routing table to dump, 871allowing you to get the whole table in a series of reasonably small requests. 872 873Response: 874 875* `routingTable` a key which contains a list of dictionaries, each containing `ip`, 876`link` and `path`. `ip` is the IPv6 address of the node, `link` is a unitless number 877between 0 inclusive and 2^32 exclusive, representing the router's opinion of the quality of 878that path, higher is better. `path` is the route to the node. 879 880* `more` to signal that there is another page of results, the engine will add a `more` key 881with the integer 1, if there isn't another page of results, the `more` key will not be added. 882 883What the data looks like: 884 885 { 886 'routingTable': [ 887 { 888 'ip': 'fce5:de17:cbde:c87b:5289:0556:8b83:c9c8', 889 'link': 4294967295, 890 'path': '0000.0000.0000.0001' 891 }, { 892 'ip': 'fcfc:2ebe:346c:7fe7:95af:a58b:2631:dead', 893 'link': 235149061, 894 'path': '0000.0000.631a.3b53' 895 }, { 896 'ip': 'fc70:772a:f803:7c4e:38bd:981b:f791:60a1', 897 'link': 271119350, 898 'path': '0000.0000.017b.b333' 899 }, 900 .............................. 901 ], 902 'more': 1 903 } 904 905Example: 906 907 >>> cjdns.NodeStore_dumpTable(0) 908 {'routingTable': [{'ip': 'fce5:de17:cbde:c87b:5289:0556:8b83:c9c8', 'link': 4294967295,.... 909 910 >>> cjdns.NodeStore_dumpTable(4) 911 {'routingTable': []} 912 913 914### SwitchPinger_ping() 915 916**Auth Required** 917 918Send a switch level ping. There is no routing table lookup and the router is not involved. 919Pinging IP addresses this way is not possible. 920 921Parameters: 922SwitchPinger_ping(required String path, String data, Int timeout) 923* String **path** the route to the node to ping eg: `0000.0000.04f5.2555` 924* String **data** (optional) for diagnosing data-dependent errors. 925* Int **timeout** (optional) milliseconds to wait for a response. 926If unspecified, will default to `DEFAULT_TIMEOUT` as defined in `SwitchPinger_admin.c` (2 seconds). 927 928Examples: 929 930 >>> cjdns.SwitchPinger_ping('0000.0000.04f5.2555') 931 {'path': '0000.0000.04f5.2555', 'data': '', 'result': 'pong', 'ms': 281} 932 933 >>> cjdns.SwitchPinger_ping('fca5:9fe0:3fa2:d576:71e6:8373:7aeb:ea11') 934 {'error': 'path was not parsable.'} 935 936 >>> cjdns.SwitchPinger_ping('0000.0000.04f5.2555', '12345abcdefg') 937 {'path': '0000.0000.04f5.2555', 'data': '12345abcdefg', 'result': 'pong', 'ms': 326} 938 939 >>> cjdns.SwitchPinger_ping('0000.0000.0405.2555') 940 {'path': '0000.0000.0405.2555', 'data': '', 'result': 'ping message caused switch error', 'ms': 278} 941 942 >>> cjdns.SwitchPinger_ping('0000.0000.04f5.2555', '', 30) 943 {'result': 'timeout', 'ms': 77} 944 945