Add support for local socket connections#1323
Conversation
| ADDR_TYPE_PADDING = 0, | ||
| ADDR_TYPE_IPV4 = 1, | ||
| ADDR_TYPE_IPV6 = 2, | ||
| ADDR_TYPE_LOCAL_SOCKET = 5 |
There was a problem hiding this comment.
I am hesitant to put this in struct wireaddr as this is also used in BOLT standard-compliant node_announcement that get broadcast as node gossip.
At minimum the numbering should not be directly after the BOLT-defined ones.
It might be better to bring up this possible use case in lightning-dev mailing list.
Alternatively we could skip this address type when sending gossip announcements.
There was a problem hiding this comment.
Agreed, it makes no sense at all to broadcast these. It hadn't occurred to me. I will look into alternatives.
There was a problem hiding this comment.
I don't think there's much value in adding local sockets to the BOLTs but I settled on a MIME type (application/lightning) and an application id (LIGHTNING) for NFC payments. I'll bring this up on the ML when I get the time since I'm not sure how to proceed on standardising these.
There was a problem hiding this comment.
If we never broadcast these there is no need to bring it up on the mailinglist, but, I am uncertain if we should be using struct wireaddr then, or some other mechanism. Intent, as I understand it, is that struct wireaddr, is for standard broadcastable messages. @rustyrussell @cdecker opinions?
|
|
||
| } | ||
|
|
||
| static char *opt_add_localsocket(const char *arg, struct lightningd *ld) |
There was a problem hiding this comment.
listconfigs is crashing in CI, probably due to not handling this case properly in add_config function.
lightning/lightningd/options.c
Lines 874 to 877 in 1a55147
|
It's cute to see these in the local address listings, but the consequences of putting it in struct wireaddr are probably not worth dealing with. Just add a '--local-socket' option perhaps? And set addr->type to ADDR_TYPE_PADDING. |
|
@rustyrussell There is the |
|
New code avoids changes to
|
|
CI is fine so I suppose it is OK. You can install Now reviewing code, please wait... |
| portnum); | ||
|
|
||
| /* Optional UNIX socket */ | ||
| if (localsocket) { |
There was a problem hiding this comment.
This comes from the fromwire_gossipctl_init. In towire_gossipctl_init a NULL pointer is converted to a 0-length array on-the-wire, I am uncertain if a 0-length array on-the-wire will be converted by fromwire_gossipctl_init to a NULL pointer. I shall check later when I can get access to my hacking node.
There was a problem hiding this comment.
No issue here: turns out 0-length arrays on-the-wire are converted to NULL by fromwire_* functions, so ok.
| io_new_conn(reach, fd, conn_init, reach); | ||
| } | ||
|
|
||
| static void try_connect_local_socket(struct daemon *daemon, const struct pubkey *id, const struct addrhint *a) |
There was a problem hiding this comment.
Might conflict with ongoing changes in #1322, that is higher priority than this I think, so please monitor that PR when it gets merged in and see if this gets conflicted (maybe not a text-level conflict but some of the functions this try_connect_local_socket calls might change their signatures and exact behavior). The first thing I can think of is that reach->succeeded has been removed in #1322, but please see that PR more for other changes that might affect this code.
Needs rebase, #1322 probably strongly affects this PR
|
Rebased, waiting to see if CI is happy |
ZmnSCPxj
left a comment
There was a problem hiding this comment.
Mostly request to change in gossipd/gossip_wire.csv. Also suggestion for localsocket arg of setup_listeners.
| } | ||
|
|
||
| static void setup_listeners(struct daemon *daemon, u16 portnum) | ||
| static void setup_listeners(struct daemon *daemon, u16 portnum, u8 *localsocket) |
There was a problem hiding this comment.
localsocket is only ever read in this function, and is effectively an input string. Maybe better to write as const char * and move the type conversion from u8* to char * to caller of setup_listeners. Or at least const u8* in the argslist.
| # Gossipd->master, I am ready. | ||
| gossipctl_init_reply,3100 | ||
|
|
||
| gossipctl_init,,lslen,u16 |
There was a problem hiding this comment.
Should this not be with the gossipctl_init fields before gossipctl_init_reply? Clearer that way.
|
Sorry @icota but a new commit in #1440 also conflicts with this: specifically the second commit by @rustyrussell moves setup of listeners to after the |
|
No worries @ZmnSCPxj, local sockets are kind of a niche application so obviously important stuff needs to go in first. I've rebased yet again. |
|
ACK 4ae3aaa |
|
|
|
Kicked CI, hopefully it is a temporary thing. |
| addr->type = ADDR_TYPE_PADDING; | ||
| addr->addrlen = strlen(ip); | ||
| addr->port = 9999; | ||
| memcpy(&addr->addr, ip, addr->addrlen); |
There was a problem hiding this comment.
Is this missing an addrlen < sizeof(addr->addr) check?
| addr.type = ADDR_TYPE_PADDING; | ||
| addr.addrlen = sizeof(sun->sun_path); | ||
| memcpy(addr.addr, &sun->sun_path, addr.addrlen); | ||
| addr.port = 9999; |
There was a problem hiding this comment.
I think 0 as magic value might be better here, just in case we use the port somewhere.
|
Just two last nits, happy to merge this soon ^^ |
|
I've amended the code, I'm thinking this might be the day 🤞 |
|
Foiled by CI |
rustyrussell
left a comment
There was a problem hiding this comment.
That got ugly fast! You can't mess with how we unmarshal ADDR_TYPE_PADDING; it's in the spec as zero length.
This is internal-only between the main daemon and gossipd. Ugly as it is, I prefer that to be explicit, rather than using wireaddr for this. Otherwise we'll risk getting local file accesses because someone gossiped a socket addresses to us!
-
Add a new message to gossipd 'towire_gossipctl_peer_addrhint_sockname' which takes a socket name; overloading the wireaddr to add local sockets gives me the creeps, since we also accept them from peers.
-
Then 'struct addrhint' needs to change in gossipd, to add a 'char *sockname' and appropriate handling.
-
Finally opt_add_addr needs enhancement, to put the socketname string somewhere if it starts with / (or, use a different option name).
| # If non-zero, port to listen on. | ||
| gossipctl_activate,,port,u16 | ||
| gossipctl_activate,,lslen,u16 | ||
| gossipctl_activate,,localsocket,lslen*u8 |
There was a problem hiding this comment.
You can use 'wirestring' here, which is much nicer, and removes cast (it's actually a char*, but wirestring is the name for purposes of the csv).
| char *rpc_filename; | ||
|
|
||
| /* Local socket for incoming connections */ | ||
| u8 *localsocket_filename; |
| addr->addrlen = 16; | ||
| break; | ||
| case ADDR_TYPE_PADDING: | ||
| addr->addrlen = ((u8)*max) - 2; |
There was a problem hiding this comment.
This is definitely wrong! We can have things in the msg after the addr. The ADDR_TYPE_PADDING case needs to simply 'return true' (addrlen is 0, there's no port).
There was a problem hiding this comment.
... and set addr->addrlen = 0.
|
Actually, after more thought, you can just introduce a new 'wireaddr_or_socket' type, and wire that up in the various places... |
|
Agree with the This would probably require special marshaling |
|
I have half a patch to do this properly. Give me 2 hours please, will push. |
|
Yuck, this ended up quite invasive. There are some nasty places to fix, too. I've got a very rough cut here: It's a bit weird since it's built on this PR then ends up reworking much of it: it might be cleaner to combine into one logical sequence. |
|
@rustyrussell your branch looks fine to me, although I mildly agree to combine to a better logical sequence. I would have moved the "single |
This replacement is a little menial, but it explicitly catches all the places where we allow a local socket. The actual implementation of opening a AF_UNIX socket is almost hidden in the patch. The detection of "valid address" is now more complex: p->addr.itype != ADDR_INTERNAL_WIREADDR || p->addr.u.wireaddr.type != ADDR_TYPE_PADDING But most places we do this, we should audit: I'm pretty sure we can't get an invalid address any more from gossipd (they may be in db, but we should fix that too). Closes: ElementsProject#1323 Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
|
OK, This has been swallowed into the "crap, where did my time go!" PR #1450... |
This replacement is a little menial, but it explicitly catches all the places where we allow a local socket. The actual implementation of opening a AF_UNIX socket is almost hidden in the patch. The detection of "valid address" is now more complex: p->addr.itype != ADDR_INTERNAL_WIREADDR || p->addr.u.wireaddr.type != ADDR_TYPE_PADDING But most places we do this, we should audit: I'm pretty sure we can't get an invalid address any more from gossipd (they may be in db, but we should fix that too). Closes: ElementsProject#1323 Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This is a flexible way to connect two instances of c-lightning via means other than the official ones. Run one side with
--localsocket=lightning-listenerand the other simply connects to the full socket path.In practice two c-lightning instances are run on separate machines with glue code connecting to sockets and forwarding data between them.
I use this to make a lightning connection (on an otherwise disconnected device) via NFC, but can be made to support bluetooth, infrared, sound or even smoke signals, anything really. Use case would be communicating with always-connected payment terminals with a mobile device that might not be.
This is way out of lightning spec but it doesn't seem to hurt anything. Let me know know what you think!