diff options
Diffstat (limited to 'sys/netinet6/in6.c')
-rw-r--r-- | sys/netinet6/in6.c | 187 |
1 files changed, 63 insertions, 124 deletions
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index ffde6da6dbb..d79c4bcfec8 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in6.c,v 1.35 2002/05/29 07:54:59 itojun Exp $ */ +/* $OpenBSD: in6.c,v 1.36 2002/06/07 04:11:51 itojun Exp $ */ /* $KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $ */ /* @@ -308,10 +308,8 @@ in6_control(so, cmd, data, ifp, p) struct in6_ifreq *ifr = (struct in6_ifreq *)data; struct in6_ifaddr *ia, *oia; struct in6_aliasreq *ifra = (struct in6_aliasreq *)data; + struct sockaddr_in6 *sa6; struct sockaddr_in6 oldaddr; -#ifdef COMPAT_IN6IFIOCTL - struct sockaddr_in6 net; -#endif int error = 0, hostIsNew, prefixIsNew; int newifaddr; time_t time_second = (time_t)time.tv_sec; @@ -354,11 +352,11 @@ in6_control(so, cmd, data, ifp, p) case SIOCAIFPREFIX_IN6: case SIOCCIFPREFIX_IN6: case SIOCSGIFPREFIX_IN6: - if (!privileged) - return(EPERM); - /*fall through*/ case SIOCGIFPREFIX_IN6: - return(in6_prefix_ioctl(so, cmd, data, ifp)); + log(LOG_NOTICE, + "prefix ioctls are now invalidated. " + "please use ifconfig.\n"); + return(EOPNOTSUPP); } switch (cmd) { @@ -373,19 +371,53 @@ in6_control(so, cmd, data, ifp, p) /* * Find address for this interface, if it exists. + * + * In netinet code, we have checked ifra_addr in SIOCSIF*ADDR operation + * only, and used the first interface address as the target of other + * operations (without checking ifra_addr). This was because netinet + * code/API assumed at most 1 interface address per interface. + * Since IPv6 allows a node to assign multiple addresses + * on a single interface, we almost always look and check the + * presence of ifra_addr, and reject invalid ones here. + * It also decreases duplicated code among SIOC*_IN6 operations. */ - if (ifra->ifra_addr.sin6_family == AF_INET6) { /* XXX */ - struct sockaddr_in6 *sa6 = - (struct sockaddr_in6 *)&ifra->ifra_addr; - + switch (cmd) { + case SIOCAIFADDR_IN6: + case SIOCSIFPHYADDR_IN6: + sa6 = &ifra->ifra_addr; + break; + case SIOCSIFADDR_IN6: + case SIOCGIFADDR_IN6: + case SIOCSIFDSTADDR_IN6: + case SIOCSIFNETMASK_IN6: + case SIOCGIFDSTADDR_IN6: + case SIOCGIFNETMASK_IN6: + case SIOCDIFADDR_IN6: + case SIOCGIFPSRCADDR_IN6: + case SIOCGIFPDSTADDR_IN6: + case SIOCGIFAFLAG_IN6: + case SIOCSNDFLUSH_IN6: + case SIOCSPFXFLUSH_IN6: + case SIOCSRTRFLUSH_IN6: + case SIOCGIFALIFETIME_IN6: + case SIOCSIFALIFETIME_IN6: + case SIOCGIFSTAT_IN6: + case SIOCGIFSTAT_ICMP6: + sa6 = &ifr->ifr_addr; + break; + default: + sa6 = NULL; + break; + } + if (sa6 && sa6->sin6_family == AF_INET6) { if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) { if (sa6->sin6_addr.s6_addr16[1] == 0) { - /* interface ID is not embedded by the user */ + /* link ID is not embedded by the user */ sa6->sin6_addr.s6_addr16[1] = - htons(ifp->if_index); + htons(ifp->if_index); } else if (sa6->sin6_addr.s6_addr16[1] != - htons(ifp->if_index)) { - return(EINVAL); /* ifid contradicts */ + htons(ifp->if_index)) { + return(EINVAL); /* link ID contradicts */ } if (sa6->sin6_scope_id) { if (sa6->sin6_scope_id != @@ -394,33 +426,32 @@ in6_control(so, cmd, data, ifp, p) sa6->sin6_scope_id = 0; /* XXX: good way? */ } } - ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr); - } + ia = in6ifa_ifpwithaddr(ifp, &sa6->sin6_addr); + } else + ia = NULL; switch (cmd) { + case SIOCSIFADDR_IN6: + case SIOCSIFDSTADDR_IN6: + case SIOCSIFNETMASK_IN6: + /* + * Since IPv6 allows a node to assign multiple addresses + * on a single interface, SIOCSIFxxx ioctls are deprecated. + */ + return(EINVAL); case SIOCDIFADDR_IN6: /* * for IPv4, we look for existing in_ifaddr here to allow - * "ifconfig if0 delete" to remove first IPv4 address on the - * interface. For IPv6, as the spec allow multiple interface - * address from the day one, we consider "remove the first one" - * semantics to be not preferable. + * "ifconfig if0 delete" to remove the first IPv4 address on + * the interface. For IPv6, as the spec allows multiple + * interface address from the day one, we consider "remove the + * first one" semantics to be not preferable. */ if (ia == NULL) return(EADDRNOTAVAIL); /* FALLTHROUGH */ case SIOCAIFADDR_IN6: - case SIOCSIFADDR_IN6: -#ifdef COMPAT_IN6IFIOCTL - case SIOCSIFDSTADDR_IN6: - case SIOCSIFNETMASK_IN6: - /* - * Since IPv6 allows a node to assign multiple addresses - * on a single interface, SIOCSIFxxx ioctls are not suitable - * and should be unused. - */ -#endif if (ifra->ifra_addr.sin6_family != AF_INET6) return(EAFNOSUPPORT); if (!privileged) @@ -548,41 +579,6 @@ in6_control(so, cmd, data, ifp, p) *((struct in6_ifextra *)ifp->if_afdata[AF_INET6])->icmp6_ifstat; break; -#ifdef COMPAT_IN6IFIOCTL /* should be unused */ - case SIOCSIFDSTADDR_IN6: - if ((ifp->if_flags & IFF_POINTOPOINT) == 0) - return(EINVAL); - oldaddr = ia->ia_dstaddr; - ia->ia_dstaddr = ifr->ifr_dstaddr; - - /* link-local index check */ - if (IN6_IS_ADDR_LINKLOCAL(&ia->ia_dstaddr.sin6_addr)) { - if (ia->ia_dstaddr.sin6_addr.s6_addr16[1] == 0) { - /* interface ID is not embedded by the user */ - ia->ia_dstaddr.sin6_addr.s6_addr16[1] - = htons(ifp->if_index); - } else if (ia->ia_dstaddr.sin6_addr.s6_addr16[1] != - htons(ifp->if_index)) { - ia->ia_dstaddr = oldaddr; - return(EINVAL); /* ifid contradicts */ - } - } - - if (ifp->if_ioctl && (error = (ifp->if_ioctl) - (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) { - ia->ia_dstaddr = oldaddr; - return(error); - } - if (ia->ia_flags & IFA_ROUTE) { - ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr; - rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); - ia->ia_ifa.ifa_dstaddr = - (struct sockaddr *)&ia->ia_dstaddr; - rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); - } - break; - -#endif case SIOCGIFALIFETIME_IN6: ifr->ifr_ifru.ifru_lifetime = ia->ia6_lifetime; break; @@ -602,63 +598,6 @@ in6_control(so, cmd, data, ifp, p) ia->ia6_lifetime.ia6t_preferred = 0; break; - case SIOCSIFADDR_IN6: - error = in6_ifinit(ifp, ia, &ifr->ifr_addr, 1); -#if 0 - /* - * the code chokes if we are to assign multiple addresses with - * the same address prefix (rtinit() will return EEXIST, which - * is not fatal actually). we will get memory leak if we - * don't do it. - * -> we may want to hide EEXIST from rtinit(). - */ - undo: - if (error && newifaddr) { - TAILQ_REMOVE(&ifp->if_addrlist, &ia->ia_ifa, ifa_list); - IFAFREE(&ia->ia_ifa); - - oia = ia; - if (oia == (ia = in6_ifaddr)) - in6_ifaddr = ia->ia_next; - else { - while (ia->ia_next && (ia->ia_next != oia)) - ia = ia->ia_next; - if (ia->ia_next) - ia->ia_next = oia->ia_next; - else { - printf("Didn't unlink in6_ifaddr " - "from list\n"); - } - } - IFAFREE(&oia->ia_ifa); - } -#endif - return error; - -#ifdef COMPAT_IN6IFIOCTL /* XXX should be unused */ - case SIOCSIFNETMASK_IN6: - ia->ia_prefixmask = ifr->ifr_addr; - bzero(&net, sizeof(net)); - net.sin6_len = sizeof(struct sockaddr_in6); - net.sin6_family = AF_INET6; - net.sin6_port = htons(0); - net.sin6_flowinfo = htonl(0); - net.sin6_addr.s6_addr32[0] - = ia->ia_addr.sin6_addr.s6_addr32[0] & - ia->ia_prefixmask.sin6_addr.s6_addr32[0]; - net.sin6_addr.s6_addr32[1] - = ia->ia_addr.sin6_addr.s6_addr32[1] & - ia->ia_prefixmask.sin6_addr.s6_addr32[1]; - net.sin6_addr.s6_addr32[2] - = ia->ia_addr.sin6_addr.s6_addr32[2] & - ia->ia_prefixmask.sin6_addr.s6_addr32[2]; - net.sin6_addr.s6_addr32[3] - = ia->ia_addr.sin6_addr.s6_addr32[3] & - ia->ia_prefixmask.sin6_addr.s6_addr32[3]; - ia->ia_net = net; - break; -#endif - case SIOCAIFADDR_IN6: prefixIsNew = 0; hostIsNew = 1; |