DF-0417 / ndflagset.c
/* ndflagset: set ND6_IFF_ACCEPT_RTADV on an interface via SIOCSIFINFO_IN6. * The global sysctl net.inet6.ip6.accept_rtadv only takes effect at * interface-attach time (nd6_ifattach, nd6.c:210); this sets the live * per-interface flag so already-attached interfaces accept Router Adverts. * Usage: ndflagset <ifname> (must run as root) */ #include <sys/ioctl.h> #include <sys/socket.h> #include <net/if.h> #include <netinet/in.h> #include <netinet6/in6_var.h> #include <netinet6/nd6.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char **argv) { if (argc < 2) { fprintf(stderr, "usage: %s ifname\n", argv[0]); return 2; } int s = socket(AF_INET6, SOCK_DGRAM, 0); if (s < 0) { perror("socket"); return 2; } struct in6_ndireq nd; memset(&nd, 0, sizeof(nd)); strncpy(nd.ifname, argv[1], IFNAMSIZ); if (ioctl(s, SIOCGIFINFO_IN6, &nd) < 0) { perror("SIOCGIFINFO_IN6"); return 2; } printf("before: flags=0x%x\n", nd.ndi.flags); nd.ndi.flags |= ND6_IFF_ACCEPT_RTADV | ND6_IFF_PERFORMNUD; /* SIOCSIFINFO_IN6 treats 0 fields as 'unspecified'; clear mtu/etc */ nd.ndi.linkmtu = 0; nd.ndi.basereachable = 0; nd.ndi.retrans = 0; nd.ndi.chlim = 0; if (ioctl(s, SIOCSIFINFO_IN6, &nd) < 0) { perror("SIOCSIFINFO_IN6"); return 2; } /* re-read */ memset(&nd, 0, sizeof(nd)); strncpy(nd.ifname, argv[1], IFNAMSIZ); ioctl(s, SIOCGIFINFO_IN6, &nd); printf("after: flags=0x%x (ACCEPT_RTADV=%d)\n", nd.ndi.flags, !!(nd.ndi.flags & ND6_IFF_ACCEPT_RTADV)); return 0; } |