* Generate a last-resort interface identifier, when the machine has no * IEEE802/EUI64 address sources. * The goal here is to get an interface identifier that is * (1) random enough and (2) does not change across reboot. * We currently use MD5(hostname) for it. * * in6 - upper 64bits are preserved */
| 114 | * in6 - upper 64bits are preserved |
| 115 | */ |
| 116 | static int |
| 117 | get_rand_ifid(struct ifnet *ifp, struct in6_addr *in6) |
| 118 | { |
| 119 | MD5_CTX ctxt; |
| 120 | struct prison *pr; |
| 121 | u_int8_t digest[16]; |
| 122 | int hostnamelen; |
| 123 | |
| 124 | pr = curthread->td_ucred->cr_prison; |
| 125 | mtx_lock(&pr->pr_mtx); |
| 126 | hostnamelen = strlen(pr->pr_hostname); |
| 127 | #if 0 |
| 128 | /* we need at least several letters as seed for ifid */ |
| 129 | if (hostnamelen < 3) { |
| 130 | mtx_unlock(&pr->pr_mtx); |
| 131 | return -1; |
| 132 | } |
| 133 | #endif |
| 134 | |
| 135 | /* generate 8 bytes of pseudo-random value. */ |
| 136 | bzero(&ctxt, sizeof(ctxt)); |
| 137 | MD5Init(&ctxt); |
| 138 | MD5Update(&ctxt, pr->pr_hostname, hostnamelen); |
| 139 | mtx_unlock(&pr->pr_mtx); |
| 140 | MD5Final(digest, &ctxt); |
| 141 | |
| 142 | /* assumes sizeof(digest) > sizeof(ifid) */ |
| 143 | bcopy(digest, &in6->s6_addr[8], 8); |
| 144 | |
| 145 | /* make sure to set "u" bit to local, and "g" bit to individual. */ |
| 146 | in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */ |
| 147 | in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */ |
| 148 | |
| 149 | /* convert EUI64 into IPv6 interface identifier */ |
| 150 | EUI64_TO_IFID(in6); |
| 151 | |
| 152 | return 0; |
| 153 | } |
| 154 | |
| 155 | static int |
| 156 | generate_tmp_ifid(u_int8_t *seed0, const u_int8_t *seed1, u_int8_t *ret) |