aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2020-04-14 18:38:52 +0200
committerPau Espin Pedrol <pespin@sysmocom.de>2020-04-15 15:10:42 +0200
commit98f8126b9852a2cc5b51f79ef01cbc68ce82ba77 (patch)
tree075dc4dcd441dd7bef9b1df5754233e6d093d98a
parenta1503b902c0b19592d5404b40e6c5d8f709f8876 (diff)
sgsnemu: Avoid adding extra autogenerated local link ipv6 addr to tun iface
It's not needed because a link-local address will be added as a result of Create Pdp Context Response. Morevoer, it fools sgsnemu ip addr verifications since it gets used on some scenarios by applications. Change-Id: I1d51f3ca91edbb3b788939982ab63264182ec2ce
-rw-r--r--sgsnemu/sgsnemu.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/sgsnemu/sgsnemu.c b/sgsnemu/sgsnemu.c
index 22be2fe..9d82145 100644
--- a/sgsnemu/sgsnemu.c
+++ b/sgsnemu/sgsnemu.c
@@ -46,6 +46,10 @@
#include <resolv.h>
#include <time.h>
+#if defined(__linux__)
+#include <linux/if_link.h>
+#endif
+
#include "config.h"
#include "../lib/tun.h"
#include "../lib/ippool.h"
@@ -999,6 +1003,37 @@ static char *proc_ipv6_conf_read(const char *dev, const char *file)
return proc_read(path);
}
+/* write a single value to a /proc file */
+static int proc_write(const char *path, const char *value)
+{
+ int ret;
+ FILE *f;
+
+ f = fopen(path, "w");
+ if (!f) {
+ SYS_ERR(DSGSN, LOGL_ERROR, 0, "fopen(%s) failed!\n", path);
+ return -1;
+ }
+
+ if ((ret = fputs(value, f)) < 0) {
+ SYS_ERR(DSGSN, LOGL_ERROR, 0, "proc_write(%s, %s) failed!\n", path, value);
+ } else {
+ ret = 0;
+ }
+ fclose(f);
+ return ret;
+}
+
+/* Write value of to /proc/sys/net/ipv6/conf file for given device.
+ * Memory is dynamically allocated, caller must free it later. */
+static int proc_ipv6_conf_write(const char *dev, const char *file, const char *value)
+{
+ const char *fmt = "/proc/sys/net/ipv6/conf/%s/%s";
+ char path[strlen(fmt) + strlen(dev) + strlen(file)+1];
+ snprintf(path, sizeof(path), fmt, dev, file);
+ return proc_write(path, value);
+}
+
static char *print_ipprot(int t)
{
struct protoent *pe = getprotobynumber(t);
@@ -1604,6 +1639,7 @@ int main(int argc, char **argv)
struct timeval tv;
int diff;
#if defined(__linux__)
+ char buf[10];
sigset_t oldmask;
#endif
@@ -1668,6 +1704,17 @@ int main(int argc, char **argv)
"Failed to create tun");
exit(1);
}
+
+#if defined(__linux__)
+ /* Avoid tunnel setting its own link-local addr automatically, we don't need it. */
+ snprintf(buf, sizeof(buf), "%u", IN6_ADDR_GEN_MODE_NONE);
+ if (proc_ipv6_conf_write(options.tun_dev_name, "addr_gen_mode", buf) < 0) {
+ SYS_ERR(DSGSN, LOGL_ERROR, errno,
+ "Failed to disable addr_gen_mode on %s\n", options.tun_dev_name);
+ exit(1);
+ }
+#endif
+
tun_set_cb_ind(tun, cb_tun_ind);
if (tun->fd > maxfd)
maxfd = tun->fd;