Re: [systemd-devel] How to get a useful peer address when doing accept(3, ...) on a systemd supplied listening socket
Hi Mantas > I have a feeling it "changes" because you're trying to give the whole > struct sockaddr to inet_pton() instead of giving just the .sin6_addr field, > so your program is trying to interpret the *port number* > (i.e. the .sin6_port which precedes .sin_addr) as part of the address... That was exactly my mistake! Thanks. At some point in my hopeless odyssey down a wrong track I tried giving the whole struct to inet_ntop() and forgot to change it back when I got everything else to work. Thanks for your help and sorry for the inconvenience. Cheers, Klaus
[systemd-devel] How to get a useful peer address when doing accept(3, ...) on a systemd supplied listening socket
Hi systemd-devel, Sorry to bug you with another user question. I have a socket activated daemon, call it mydaemon, and I have trouble finding out who connects to it. mydaemon.socket contains: [Socket] ListenStream= When I connect using IPv4 using nc -4 localhost then mydaemon does sockaddr_in6 peer; socklen_t peer_size=sizeof(peer); accept(3,(struct sockaddr *),sizeof(peer)) Afterwards, peer.sin6_family is AF_INET6 and peer.sin6_addr contains some gibberish like a00:e5ae:: If I connect more than once, the gibberish changes from connection to connection. Something similar happens if I connect using IPv6. If I change mydaemon.socket to [Socket] ListenStream=0.0.0.0: Then peer.sin6_family becomes AF_INET as it should. But if peer is cast to struct sockaddr_in then peer.sin_addr still contains gibberish like 2.0.191.150 (I expected something like 127.0.0.1 or 192.168.0.99). When I connect from other machines, the peer address still is gibberish. If mydaemon creates the listening socket, I can easily get the peer address. I suspect that when systemd creates the listening socket then accept(3,...) returns a socket which is connected to a local socket created by systemd. QUESTION: Is that suspicion correct? And if yes, is there are way to recover the address of the actually connecting peer? Cheers, Klaus
Re: [systemd-devel] Is it possible to let systemd create a listening socket and yet be able to have that socket activate nothing, at least temporarily?
Hi Lennart, > Can't you run your upgrade script in idempotent way as a helper > service that is pulled in by your main daemon and ordered before it, > but conditions itself out if it already did its job? that's usually > the most robust way, since then it's sufficient to just restart your > daemon or reboot, and everything will always catch up correctly. > i.e. if you have foo-daemon.socket + foo-daemon.service then define > foo-upgrade.service that is pulled in from foo-daemon.service via > `Wants=foo-upgrade.service` + `After=foo-upgrade.service`. And then > add `ConditionFileExists=!/some/touch/file` to `foo-upgrade.service` to > make it a NOP if things have already been updated, using a touch > file. (some better, smarter condition check might work as well, see > man pages of things systemd can check for you). That is a great pattern! A Type=oneshot seems useful for the upgrade process. For the record, I have appended what ended up working. Thanks! Cheers, Klaus --- The following three unit files open a listening socket, run the myupgrade service, and only then start the /usr/bin/mydaemon service. The socket listens while the myupgrade service runs so that clients can connect. But the clients are queued until myupgrade has finished and /usr/bin/mydaemon starts accepting connections. mydeamon.service: [Unit] Description=service that does something After=mydaemon.socket Requires=mydaemon.socket After=myupgrade.service Wants=myupgrade.service [Install] WantedBy=multi-user.target [Service] Type=simple ExecStart=/usr/bin/mydaemon myupgrade.service: [Unit] Description=service to run before mydaemon [Service] Type=oneshot ExecStart=/usr/bin/bash -c "echo goodnight;sleep 60;echo goodmorning" mydeamon.socket [Unit] Description=mydaemon listen socket [Socket] ListenStream= [Install] WantedBy=sockets.target
Re: [systemd-devel] Is it possible to let systemd create a listening socket and yet be able to have that socket activate nothing, at least temporarily?
Hi Mantas, Thanks for the suggestion. I will take a look at it. When i do not want to do int flag=1; int rv=setsockopt(listen_fd,SOL_SOCKET,SO_REUSEADDR,,sizeof(flag)); the central problem will be to avoid the 1 minute delay Cheers, Klaus Fra: Mantas Mikulėnas Sendt: 7. oktober 2022 09:51 Til: Klaus Ebbe Grue Cc: systemd-devel@lists.freedesktop.org Emne: Re: [systemd-devel] Is it possible to let systemd create a listening socket and yet be able to have that socket activate nothing, at least temporarily? You don't often get email from graw...@gmail.com. Learn why this is important<https://aka.ms/LearnAboutSenderIdentification> On Fri, Oct 7, 2022 at 10:24 AM Klaus Ebbe Grue mailto:g...@di.ku.dk>> wrote: Hi systemd-devel, I have a user question which I take the liberty to send here since "about systemd-devel" says "... it's also OK to direct user questions to this mailing list ...". I have a daemon, /usr/bin/mydaemon, which listens on one and only one TCP port, say , and which does no more than communicating over and creating, reading, writing and deleting files in /home/me/mydaemon/. Mydaemon leaves it to systemd to create a socket which listens at . It is unimportant whether or not mydaemon is started at boot and it is also unimportant whether or not mydaemon is socket activated. As long as it is at least one of the two. Now I want to upgrade mydaemon to a new version using a script, without race conditions and without closing the listening socket. I want the listening socket to stay open since otherwise there can be a one minute interval during which it is impossible to reopen . If it is just a clean upgrade, the script could replace /usr/bin/mydaemon, then stop mydaemon. If the daemon is socket activated there is no more to do. If the daemon is activated only on boot then the script must end up restarting mydaemon. But now I want to do some more while mydaemon is not running. It could be that my script should take a backup of /home/me/mydaemon/ in case things go wrong. It could be the script should translate some file in /home/me/mydaemon/ to some new format required by the new mydaemon or whatever. So I need to stop mydaemon in such a way that mydaemon cannot wake up while my script fiddles with /home/me/mydaemon/. Deploy the new version of your daemon to another location (/home/me/mydaemon.new/), perform all processing/conversions that are necessary, *then* stop the socket, `mv mydaemon mydaemon.old`, stop the service, `mv mydaemon.new mydaemon`, start the socket again. The interval for this will be more like half a second than a minute. -- Mantas Mikulėnas
Re: [systemd-devel] Is it possible to let systemd create a listening socket and yet be able to have that socket activate nothing, at least temporarily?
Hi Michael, > Unfortunately not. You'd need some kind of "maintenance" mode ... Thanks a lot. I will go with the maintenance mode without fearing to have missed some systemd feature. Cheers, Klaus
[systemd-devel] Is it possible to let systemd create a listening socket and yet be able to have that socket activate nothing, at least temporarily?
Hi systemd-devel, I have a user question which I take the liberty to send here since "about systemd-devel" says "... it's also OK to direct user questions to this mailing list ...". I have a daemon, /usr/bin/mydaemon, which listens on one and only one TCP port, say , and which does no more than communicating over and creating, reading, writing and deleting files in /home/me/mydaemon/. Mydaemon leaves it to systemd to create a socket which listens at . It is unimportant whether or not mydaemon is started at boot and it is also unimportant whether or not mydaemon is socket activated. As long as it is at least one of the two. Now I want to upgrade mydaemon to a new version using a script, without race conditions and without closing the listening socket. I want the listening socket to stay open since otherwise there can be a one minute interval during which it is impossible to reopen . If it is just a clean upgrade, the script could replace /usr/bin/mydaemon, then stop mydaemon. If the daemon is socket activated there is no more to do. If the daemon is activated only on boot then the script must end up restarting mydaemon. But now I want to do some more while mydaemon is not running. It could be that my script should take a backup of /home/me/mydaemon/ in case things go wrong. It could be the script should translate some file in /home/me/mydaemon/ to some new format required by the new mydaemon or whatever. So I need to stop mydaemon in such a way that mydaemon cannot wake up while my script fiddles with /home/me/mydaemon/. According to https://0pointer.de/blog/projects/three-levels-of-off it seems that that was possible in 2011: just do "systemctl disable mydaemon.service". But when I try that, mydaemon still wakes up if I connect to using eg netcat. I have also tried to mask mydaemon. But if I then connect to using netcat, then netcat gets kicked of. And if I try again then is no longer listening. QUESTION: Is it possible to let systemd create a listening socket and yet be able to have that socket activate nothing, at least temporarily? Cheers, Klaus