| 153 | } |
| 154 | |
| 155 | static int |
| 156 | generate_tmp_ifid(u_int8_t *seed0, const u_int8_t *seed1, u_int8_t *ret) |
| 157 | { |
| 158 | MD5_CTX ctxt; |
| 159 | u_int8_t seed[16], digest[16], nullbuf[8]; |
| 160 | u_int32_t val32; |
| 161 | |
| 162 | /* If there's no history, start with a random seed. */ |
| 163 | bzero(nullbuf, sizeof(nullbuf)); |
| 164 | if (bcmp(nullbuf, seed0, sizeof(nullbuf)) == 0) { |
| 165 | int i; |
| 166 | |
| 167 | for (i = 0; i < 2; i++) { |
| 168 | val32 = arc4random(); |
| 169 | bcopy(&val32, seed + sizeof(val32) * i, sizeof(val32)); |
| 170 | } |
| 171 | } else |
| 172 | bcopy(seed0, seed, 8); |
| 173 | |
| 174 | /* copy the right-most 64-bits of the given address */ |
| 175 | /* XXX assumption on the size of IFID */ |
| 176 | bcopy(seed1, &seed[8], 8); |
| 177 | |
| 178 | if (0) { /* for debugging purposes only */ |
| 179 | int i; |
| 180 | |
| 181 | printf("generate_tmp_ifid: new randomized ID from: "); |
| 182 | for (i = 0; i < 16; i++) |
| 183 | printf("%02x", seed[i]); |
| 184 | printf(" "); |
| 185 | } |
| 186 | |
| 187 | /* generate 16 bytes of pseudo-random value. */ |
| 188 | bzero(&ctxt, sizeof(ctxt)); |
| 189 | MD5Init(&ctxt); |
| 190 | MD5Update(&ctxt, seed, sizeof(seed)); |
| 191 | MD5Final(digest, &ctxt); |
| 192 | |
| 193 | /* |
| 194 | * RFC 3041 3.2.1. (3) |
| 195 | * Take the left-most 64-bits of the MD5 digest and set bit 6 (the |
| 196 | * left-most bit is numbered 0) to zero. |
| 197 | */ |
| 198 | bcopy(digest, ret, 8); |
| 199 | ret[0] &= ~EUI64_UBIT; |
| 200 | |
| 201 | /* |
| 202 | * XXX: we'd like to ensure that the generated value is not zero |
| 203 | * for simplicity. If the caclculated digest happens to be zero, |
| 204 | * use a random non-zero value as the last resort. |
| 205 | */ |
| 206 | if (bcmp(nullbuf, ret, sizeof(nullbuf)) == 0) { |
| 207 | nd6log((LOG_INFO, |
| 208 | "generate_tmp_ifid: computed MD5 value is zero.\n")); |
| 209 | |
| 210 | val32 = arc4random(); |
| 211 | val32 = 1 + (val32 % (0xffffffff - 1)); |
| 212 | } |