Index: uspace/srv/net/inetsrv/sroute.c
===================================================================
--- uspace/srv/net/inetsrv/sroute.c	(revision a35b458e9db1ca95e679799dc7c1b12c83359ca3)
+++ uspace/srv/net/inetsrv/sroute.c	(revision 1bbc6dc64db723b798344b36c45a156bdd6ccc13)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2012 Jiri Svoboda
+ * Copyright (c) 2024 Jiri Svoboda
  * All rights reserved.
  *
@@ -40,4 +40,6 @@
 #include <io/log.h>
 #include <ipc/loc.h>
+#include <sif.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <str.h>
@@ -210,4 +212,201 @@
 }
 
+/** Load static route from SIF node.
+ *
+ * @param nroute SIF node to load static route from
+ * @return EOK on success or an error code
+ */
+static errno_t inet_sroute_load(sif_node_t *nroute)
+{
+	errno_t rc;
+	const char *sid;
+	const char *sdest;
+	const char *srouter;
+	const char *name;
+	char *endptr;
+	int id;
+	inet_naddr_t dest;
+	inet_addr_t router;
+	inet_sroute_t *sroute;
+
+	sid = sif_node_get_attr(nroute, "id");
+	if (sid == NULL)
+		return EIO;
+
+	sdest = sif_node_get_attr(nroute, "dest");
+	if (sdest == NULL)
+		return EIO;
+
+	srouter = sif_node_get_attr(nroute, "router");
+	if (srouter == NULL)
+		return EIO;
+
+	name = sif_node_get_attr(nroute, "name");
+	if (name == NULL)
+		return EIO;
+
+	id = strtoul(sid, &endptr, 10);
+	if (*endptr != '\0')
+		return EIO;
+
+	rc = inet_naddr_parse(sdest, &dest, NULL);
+	if (rc != EOK)
+		return EIO;
+
+	rc = inet_addr_parse(srouter, &router, NULL);
+	if (rc != EOK)
+		return EIO;
+
+	sroute = inet_sroute_new();
+	if (sroute == NULL)
+		return ENOMEM;
+
+	sroute->id = id;
+	sroute->dest = dest;
+	sroute->router = router;
+	sroute->name = str_dup(name);
+
+	if (sroute->name == NULL) {
+		inet_sroute_delete(sroute);
+		return ENOMEM;
+	}
+
+	inet_sroute_add(sroute);
+	return EOK;
+}
+
+/** Load static routes from SIF node.
+ *
+ * @param nroutes SIF node to load static routes from
+ * @return EOK on success or an error code
+ */
+errno_t inet_sroutes_load(sif_node_t *nroutes)
+{
+	sif_node_t *nroute;
+	const char *ntype;
+	errno_t rc;
+
+	nroute = sif_node_first_child(nroutes);
+	while (nroute != NULL) {
+		ntype = sif_node_get_type(nroute);
+		if (str_cmp(ntype, "route") != 0) {
+			rc = EIO;
+			goto error;
+		}
+
+		rc = inet_sroute_load(nroute);
+		if (rc != EOK)
+			goto error;
+
+		nroute = sif_node_next_child(nroute);
+	}
+
+	return EOK;
+error:
+	return rc;
+}
+
+/** Save static route to SIF node.
+ *
+ * @param sroute Static route
+ * @param nroute SIF node to save static route to
+ * @return EOK on success or an error code
+ */
+static errno_t inet_sroute_save(inet_sroute_t *sroute, sif_node_t *nroute)
+{
+	char *str = NULL;
+	errno_t rc;
+	int rv;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_sroute_save(%p, %p)",
+	    sroute, nroute);
+
+	/* id */
+
+	rv = asprintf(&str, "%lu", sroute->id);
+	if (rv < 0) {
+		str = NULL;
+		rc = ENOMEM;
+		goto error;
+	}
+
+	rc = sif_node_set_attr(nroute, "id", str);
+	if (rc != EOK)
+		goto error;
+
+	free(str);
+	str = NULL;
+
+	/* dest */
+
+	rc = inet_naddr_format(&sroute->dest, &str);
+	if (rc != EOK)
+		goto error;
+
+	rc = sif_node_set_attr(nroute, "dest", str);
+	if (rc != EOK)
+		goto error;
+
+	free(str);
+	str = NULL;
+
+	/* router */
+
+	rc = inet_addr_format(&sroute->router, &str);
+	if (rc != EOK)
+		goto error;
+
+	rc = sif_node_set_attr(nroute, "router", str);
+	if (rc != EOK)
+		goto error;
+
+	/* name */
+
+	rc = sif_node_set_attr(nroute, "name", sroute->name);
+	if (rc != EOK)
+		goto error;
+
+	free(str);
+
+	return rc;
+error:
+	if (str != NULL)
+		free(str);
+	return rc;
+}
+
+/** Save static routes to SIF node.
+ *
+ * @param nroutes SIF node to save static routes to
+ * @return EOK on success or an error code
+ */
+errno_t inet_sroutes_save(sif_node_t *nroutes)
+{
+	sif_node_t *nroute;
+	errno_t rc;
+
+	log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_sroutes_save()");
+
+	fibril_mutex_lock(&sroute_list_lock);
+
+	list_foreach(sroute_list, sroute_list, inet_sroute_t, sroute) {
+		if (sroute->temp == false) {
+			rc = sif_node_append_child(nroutes, "route", &nroute);
+			if (rc != EOK)
+				goto error;
+
+			rc = inet_sroute_save(sroute, nroute);
+			if (rc != EOK)
+				goto error;
+		}
+	}
+
+	fibril_mutex_unlock(&sroute_list_lock);
+	return EOK;
+error:
+	fibril_mutex_unlock(&sroute_list_lock);
+	return rc;
+}
+
 /** @}
  */
