The IPv6CP code generates interface IDs based on getmicrouptime(),
in the sppp_suggest_ip6_addr() function.

Interface IDs provide parts of the link-local addresses used for
the endpoints of the point-to-point link.

RFC 5072 says the ifid may be generated from a good random source
if available. We have that, so use it. This ignores the RFC's
recommendation to use a reproducible ifid, but so did the code
based on getmicrouptime().

This also removes a confusing clutch where the ifid-generator is run
again and the caller checks if the same result is the same as last time.
That doesn't even work with getmicrouptime(), so I've removed the clutch.
Note that the clutch only runs if the IPV6CP_MYIFID_DYN flag is set,
which is never set, so technically this is a dead code path. I intend
to rework this entirely later, but want to focus discussion and review
on the ifid generator for now.

I've also removed a useless check for a non-NULL output argument of
the generator function. It doesn't make sense to call it with a NULL
output argument.

ok?

Index: if_spppsubr.c
===================================================================
RCS file: /cvs/src/sys/net/if_spppsubr.c,v
retrieving revision 1.110
diff -u -p -r1.110 if_spppsubr.c
--- if_spppsubr.c       5 Nov 2013 15:32:48 -0000       1.110
+++ if_spppsubr.c       6 Nov 2013 09:07:06 -0000
@@ -320,7 +320,6 @@ HIDE void sppp_get_ip6_addrs(struct sppp
                               struct in6_addr *dst, struct in6_addr *srcmask);
 HIDE void sppp_set_ip6_addr(struct sppp *sp, const struct in6_addr *src);
 HIDE void sppp_gen_ip6_addr(struct sppp *sp, struct in6_addr *addr);
-HIDE void sppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *suggest);
 
 HIDE void sppp_pap_input(struct sppp *sp, struct mbuf *m);
 HIDE void sppp_pap_init(struct sppp *sp);
@@ -3286,7 +3285,7 @@ sppp_ipv6cp_RCR(struct sppp *sp, struct 
                                 * Conf-Nak, suggest hisaddr
                                 */
                                type = CONF_NAK;
-                               sppp_suggest_ip6_addr(sp, &suggestaddr);
+                               sppp_gen_ip6_addr(sp, &suggestaddr);
                                bcopy(&suggestaddr.s6_addr[8], &p[2], 8);
                        }
                        if (debug)
@@ -3404,20 +3403,6 @@ sppp_ipv6cp_RCN_nak(struct sppp *sp, str
                         * we accept his offer.
                         */
                        if (sp->ipv6cp.flags & IPV6CP_MYIFID_DYN) {
-                               struct in6_addr lastsuggest;
-                               /*
-                                * If <suggested myaddr from peer> equals to
-                                * <hisaddr we have suggested last time>,
-                                * we have a collision.  generate new random
-                                * ifid.
-                                */
-                               sppp_suggest_ip6_addr(sp,&lastsuggest);
-                               if (IN6_ARE_ADDR_EQUAL(&suggestaddr,
-                                                &lastsuggest)) {
-                                       if (debug)
-                                               addlog(" [random]");
-                                       sppp_gen_ip6_addr(sp, &suggestaddr);
-                               }
                                sppp_set_ip6_addr(sp, &suggestaddr);
                                if (debug)
                                        addlog(" [agree]");
@@ -4781,15 +4766,6 @@ sppp_get_ip6_addrs(struct sppp *sp, stru
 
 #ifdef IPV6CP_MYIFID_DYN
 /*
- * Generate random ifid.
- */
-HIDE void
-sppp_gen_ip6_addr(struct sppp *sp, struct in6_addr *addr)
-{
-       /* TBD */
-}
-
-/*
  * Set my IPv6 address.  Must be called at splnet.
  */
 HIDE void
@@ -4822,27 +4798,26 @@ sppp_set_ip6_addr(struct sppp *sp, const
 #endif
 
 /*
- * Suggest a candidate address to be used by peer.
+ * Generate random ifid.
  */
 HIDE void
-sppp_suggest_ip6_addr(struct sppp *sp, struct in6_addr *suggest)
+sppp_gen_ip6_addr(struct sppp *sp, struct in6_addr *suggest)
 {
        struct in6_addr myaddr;
-       struct timeval tv;
+       u_int32_t random;
 
-       sppp_get_ip6_addrs(sp, &myaddr, 0, 0);
+       sppp_get_ip6_addrs(sp, &myaddr, NULL, NULL);
 
        myaddr.s6_addr[8] &= ~0x02;     /* u bit to "local" */
-       getmicrouptime(&tv);
-       if ((tv.tv_usec & 0xff) == 0 && (tv.tv_sec & 0xff) == 0) {
+       random = arc4random();
+       if ((random & 0xff) == 0 && (random & 0xff00) == 0) {
                myaddr.s6_addr[14] ^= 0xff;
                myaddr.s6_addr[15] ^= 0xff;
        } else {
-               myaddr.s6_addr[14] ^= (tv.tv_usec & 0xff);
-               myaddr.s6_addr[15] ^= (tv.tv_sec & 0xff);
-       }
-       if (suggest)
-               bcopy(&myaddr, suggest, sizeof(myaddr));
+               myaddr.s6_addr[14] ^= (random & 0xff);
+               myaddr.s6_addr[15] ^= ((random & 0xff00) >> 8);
+       }
+       bcopy(&myaddr, suggest, sizeof(myaddr));
 }
 #endif /*INET6*/
 

Reply via email to