Net-SNMP's configuration files are not resilient to power failure.
Users created with net-snmp-create-v3-user are missing from /etc/snmp/snmpd.conf after immidiate power failure event and that /var/lib/net-snmp/snmpd.conf is empty.
How to reproduce:
[root@desktop]# grep testuser /etc/snmp/snmpd.conf /var/lib/net-snmp/snmpd.conf
[root@desktop]# systemctl stop snmpd
[root@desktop]# /usr/bin/net-snmp-create-v3-user -A testpass testuser
[root@desktop]# grep testuser /etc/snmp/snmpd.conf /var/lib/net-snmp/snmpd.conf
/etc/snmp/snmpd.conf:rwuser testuser
/var/lib/net-snmp/snmpd.conf:createUser testuser MD5 "testpass" DES
[root@desktop]# systemctl start snmpd
Force power off and reconnect.
[root@desktop]# grep testuser /etc/snmp/snmpd.conf /var/lib/net-snmp/snmpd.conf
output is empty
Expected results:
/etc/snmp/snmpd.conf contains the newly added user.
/var/lib/net-snmp/snmpd.conf is present on file system.
Additional info:
This behaviour was observed for XFS root filesystems, on Ext's it works as expected.
Patch is attached. Please consider to add this patch to next Net-SNMP release.
I think you'd better fflush(out) first, right, or there may be data sitting in stdio's buffers that haven't made it to the file descriptor by the time you ask to fsync the file descriptor.
The man page for fsync on Linux says,
Do you think net-snmp should do this too?
Also, this adds as many fsync()s as there are rows in the tables being stored - basically every line gets synced to disk individually, possibly slowing this operation down significantly. I realize that this is the most straightforward way to accomplish your goal given the structure of the code, but perhaps it would be better to add an explicit
read_config_flush(const char *type)
which callsfsync()
(and maybe does the magic that the man page describes on the directory too), and call that after all of the callbacks have been called.(Or a rearchitecting of this system that keeps a file open while it's calling the callbacks, so that we can just call fflush()/fsync() at the end before closing it, which would be the most efficient but that is a major change.)
Or, instead of rewriting the file, write a new file and rename it when the file is complete.
+1 from me for Niels' proposal.
I am not sure, if creating temporary file and moving/renaming it to new location is suitable for all calls of read_config_store method due in this case (create new record for user) you just append to the end of file new line with information about new user. Personally, I think the best solution would be to add an explicit function for this (e.g. already mentioned read_config_flush) due this function (for meet goal of this request) is required to call only in usm_save_user method. But I am open to all of yours suggestions. What do you think about it?