+++ /dev/null
-/*
- * $Id$
- *
- * Authors:
- * Lars Fenneberg <lf@elemental.net>
- *
- * This software is Copyright 1996,1997 by the above mentioned author(s),
- * All Rights Reserved.
- *
- * The license which is distributed with this software in the file COPYRIGHT
- * applies to this software. If your distribution is missing this file, you
- * may request it from <pekkas@netcore.fi>.
- *
- */
-
-#include "config.h"
-#include "includes.h"
-#include "radvd.h"
-#include "defaults.h"
-#include "pathnames.h" /* for PATH_PROC_NET_IF_INET6 */
-
-#ifndef IPV6_ADDR_LINKLOCAL
-#define IPV6_ADDR_LINKLOCAL 0x0020U
-#endif
-
-/*
- * this function gets the hardware type and address of an interface,
- * determines the link layer token length and checks it against
- * the defined prefixes
- */
-int
-setup_deviceinfo(int sock, struct Interface *iface)
-{
- struct ifreq ifr;
- struct AdvPrefix *prefix;
- char zero[sizeof(iface->if_addr)];
-
- strncpy(ifr.ifr_name, iface->Name, IFNAMSIZ-1);
- ifr.ifr_name[IFNAMSIZ-1] = '\0';
-
- if (ioctl(sock, SIOCGIFMTU, &ifr) < 0) {
- flog(LOG_ERR, "ioctl(SIOCGIFMTU) failed for %s: %s",
- iface->Name, strerror(errno));
- return (-1);
- }
-
- dlog(LOG_DEBUG, 3, "mtu for %s is %d", iface->Name, ifr.ifr_mtu);
- iface->if_maxmtu = ifr.ifr_mtu;
-
- if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0)
- {
- flog(LOG_ERR, "ioctl(SIOCGIFHWADDR) failed for %s: %s",
- iface->Name, strerror(errno));
- return (-1);
- }
-
- dlog(LOG_DEBUG, 3, "hardware type for %s is %d", iface->Name,
- ifr.ifr_hwaddr.sa_family);
-
- switch(ifr.ifr_hwaddr.sa_family)
- {
- case ARPHRD_ETHER:
- iface->if_hwaddr_len = 48;
- iface->if_prefix_len = 64;
- break;
-#ifdef ARPHRD_FDDI
- case ARPHRD_FDDI:
- iface->if_hwaddr_len = 48;
- iface->if_prefix_len = 64;
- break;
-#endif /* ARPHDR_FDDI */
-#ifdef ARPHRD_ARCNET
- case ARPHRD_ARCNET:
- iface->if_hwaddr_len = 8;
- iface->if_prefix_len = -1;
- iface->if_maxmtu = -1;
- break;
-#endif /* ARPHDR_ARCNET */
- default:
- iface->if_hwaddr_len = -1;
- iface->if_prefix_len = -1;
- iface->if_maxmtu = -1;
- break;
- }
-
- dlog(LOG_DEBUG, 3, "link layer token length for %s is %d", iface->Name,
- iface->if_hwaddr_len);
-
- dlog(LOG_DEBUG, 3, "prefix length for %s is %d", iface->Name,
- iface->if_prefix_len);
-
- if (iface->if_hwaddr_len != -1) {
- unsigned int if_hwaddr_len_bytes = (iface->if_hwaddr_len + 7) >> 3;
-
- if (if_hwaddr_len_bytes > sizeof(iface->if_hwaddr)) {
- flog(LOG_ERR, "address length %d too big for %s", if_hwaddr_len_bytes, iface->Name);
- return(-2);
- }
- memcpy(iface->if_hwaddr, ifr.ifr_hwaddr.sa_data, if_hwaddr_len_bytes);
-
- memset(zero, 0, sizeof(zero));
- if (!memcmp(iface->if_hwaddr, zero, if_hwaddr_len_bytes))
- flog(LOG_WARNING, "WARNING, MAC address on %s is all zero!",
- iface->Name);
- }
-
- prefix = iface->AdvPrefixList;
- while (prefix)
- {
- if ((iface->if_prefix_len != -1) &&
- (iface->if_prefix_len != prefix->PrefixLen))
- {
- flog(LOG_WARNING, "prefix length should be %d for %s",
- iface->if_prefix_len, iface->Name);
- }
-
- prefix = prefix->next;
- }
-
- return (0);
-}
-
-/*
- * this function extracts the link local address and interface index
- * from PATH_PROC_NET_IF_INET6. Note: 'sock' unused in Linux.
- */
-int setup_linklocal_addr(int sock, struct Interface *iface)
-{
- FILE *fp;
- char str_addr[40];
- unsigned int plen, scope, dad_status, if_idx;
- char devname[IFNAMSIZ];
-
- if ((fp = fopen(PATH_PROC_NET_IF_INET6, "r")) == NULL)
- {
- flog(LOG_ERR, "can't open %s: %s", PATH_PROC_NET_IF_INET6,
- strerror(errno));
- return (-1);
- }
-
- while (fscanf(fp, "%32s %x %02x %02x %02x %15s\n",
- str_addr, &if_idx, &plen, &scope, &dad_status,
- devname) != EOF)
- {
- if (scope == IPV6_ADDR_LINKLOCAL &&
- strcmp(devname, iface->Name) == 0)
- {
- struct in6_addr addr;
- unsigned int ap;
- int i;
-
- for (i=0; i<16; i++)
- {
- sscanf(str_addr + i * 2, "%02x", &ap);
- addr.s6_addr[i] = (unsigned char)ap;
- }
- memcpy(&iface->if_addr, &addr, sizeof(iface->if_addr));
-
- iface->if_index = if_idx;
- fclose(fp);
- return 0;
- }
- }
-
- flog(LOG_ERR, "no linklocal address configured for %s", iface->Name);
- fclose(fp);
- return (-1);
-}
-
-int setup_allrouters_membership(int sock, struct Interface *iface)
-{
- struct ipv6_mreq mreq;
-
- memset(&mreq, 0, sizeof(mreq));
- mreq.ipv6mr_interface = iface->if_index;
-
- /* ipv6-allrouters: ff02::2 */
- mreq.ipv6mr_multiaddr.s6_addr32[0] = htonl(0xFF020000);
- mreq.ipv6mr_multiaddr.s6_addr32[3] = htonl(0x2);
-
- if (setsockopt(sock, SOL_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
- {
- /* linux-2.6.12-bk4 returns error with HUP signal but keep listening */
- if (errno != EADDRINUSE)
- {
- flog(LOG_ERR, "can't join ipv6-allrouters on %s", iface->Name);
- return (-1);
- }
- }
-
- return (0);
-}
-
-int check_allrouters_membership(int sock, struct Interface *iface)
-{
- #define ALL_ROUTERS_MCAST "ff020000000000000000000000000002"
-
- FILE *fp;
- unsigned int if_idx, allrouters_ok=0;
- char addr[32+1];
- int ret=0;
-
- if ((fp = fopen(PATH_PROC_NET_IGMP6, "r")) == NULL)
- {
- flog(LOG_ERR, "can't open %s: %s", PATH_PROC_NET_IGMP6,
- strerror(errno));
- return (-1);
- }
-
- while ( (ret=fscanf(fp, "%u %*s %32[0-9A-Fa-f] %*x %*x %*x\n", &if_idx, addr)) != EOF) {
- if (ret == 2) {
- if (iface->if_index == if_idx) {
- if (strncmp(addr, ALL_ROUTERS_MCAST, sizeof(addr)) == 0)
- allrouters_ok = 1;
- }
- }
- }
-
- fclose(fp);
-
- if (!allrouters_ok) {
- flog(LOG_WARNING, "resetting ipv6-allrouters membership on %s", iface->Name);
- setup_allrouters_membership(sock, iface);
- }
-
- return(0);
-}
-
-static int
-set_interface_var(const char *iface,
- const char *var, const char *name,
- uint32_t val)
-{
- FILE *fp;
- char spath[64+IFNAMSIZ]; /* XXX: magic constant */
- snprintf(spath, sizeof(spath), var, iface);
-
- fp = fopen(spath, "w");
- if (!fp) {
- if (name)
- flog(LOG_ERR, "failed to set %s (%u) for %s",
- name, val, iface);
- return -1;
- }
- fprintf(fp, "%u", val);
- fclose(fp);
-
- return 0;
-}
-
-int
-set_interface_linkmtu(const char *iface, uint32_t mtu)
-{
- return set_interface_var(iface,
- PROC_SYS_IP6_LINKMTU, "LinkMTU",
- mtu);
-}
-
-int
-set_interface_curhlim(const char *iface, uint8_t hlim)
-{
- return set_interface_var(iface,
- PROC_SYS_IP6_CURHLIM, "CurHopLimit",
- hlim);
-}
-
-int
-set_interface_reachtime(const char *iface, uint32_t rtime)
-{
- int ret;
- ret = set_interface_var(iface,
- PROC_SYS_IP6_BASEREACHTIME_MS,
- NULL,
- rtime);
- if (ret)
- ret = set_interface_var(iface,
- PROC_SYS_IP6_BASEREACHTIME,
- "BaseReachableTimer",
- rtime / 1000);
- return ret;
-}
-
-int
-set_interface_retranstimer(const char *iface, uint32_t rettimer)
-{
- int ret;
- ret = set_interface_var(iface,
- PROC_SYS_IP6_RETRANSTIMER_MS,
- NULL,
- rettimer);
- if (ret)
- ret = set_interface_var(iface,
- PROC_SYS_IP6_RETRANSTIMER,
- "RetransTimer",
- rettimer / 1000);
- return ret;
-}
-