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