* compute NI group address, based on the current hostname setting. * see RFC 4620. * * when ifp == NULL, the caller is responsible for filling scopeid. * * If oldmcprefix == 1, FF02:0:0:0:0:2::/96 is used for NI group address * while it is FF02:0:0:0:0:2:FF00::/104 in RFC 4620. */
| 578 | * while it is FF02:0:0:0:0:2:FF00::/104 in RFC 4620. |
| 579 | */ |
| 580 | static int |
| 581 | in6_nigroup0(struct ifnet *ifp, const char *name, int namelen, |
| 582 | struct in6_addr *in6, int oldmcprefix) |
| 583 | { |
| 584 | struct prison *pr; |
| 585 | const char *p; |
| 586 | u_char *q; |
| 587 | MD5_CTX ctxt; |
| 588 | u_int8_t digest[16]; |
| 589 | char l; |
| 590 | char n[64]; /* a single label must not exceed 63 chars */ |
| 591 | |
| 592 | /* |
| 593 | * If no name is given and namelen is -1, |
| 594 | * we try to do the hostname lookup ourselves. |
| 595 | */ |
| 596 | if (!name && namelen == -1) { |
| 597 | pr = curthread->td_ucred->cr_prison; |
| 598 | mtx_lock(&pr->pr_mtx); |
| 599 | name = pr->pr_hostname; |
| 600 | namelen = strlen(name); |
| 601 | } else |
| 602 | pr = NULL; |
| 603 | if (!name || !namelen) { |
| 604 | if (pr != NULL) |
| 605 | mtx_unlock(&pr->pr_mtx); |
| 606 | return -1; |
| 607 | } |
| 608 | |
| 609 | p = name; |
| 610 | while (p && *p && *p != '.' && p - name < namelen) |
| 611 | p++; |
| 612 | if (p == name || p - name > sizeof(n) - 1) { |
| 613 | if (pr != NULL) |
| 614 | mtx_unlock(&pr->pr_mtx); |
| 615 | return -1; /* label too long */ |
| 616 | } |
| 617 | l = p - name; |
| 618 | strncpy(n, name, l); |
| 619 | if (pr != NULL) |
| 620 | mtx_unlock(&pr->pr_mtx); |
| 621 | n[(int)l] = '\0'; |
| 622 | for (q = n; *q; q++) { |
| 623 | if ('A' <= *q && *q <= 'Z') |
| 624 | *q = *q - 'A' + 'a'; |
| 625 | } |
| 626 | |
| 627 | /* generate 16 bytes of pseudo-random value. */ |
| 628 | bzero(&ctxt, sizeof(ctxt)); |
| 629 | MD5Init(&ctxt); |
| 630 | MD5Update(&ctxt, &l, sizeof(l)); |
| 631 | MD5Update(&ctxt, n, l); |
| 632 | MD5Final(digest, &ctxt); |
| 633 | |
| 634 | bzero(in6, sizeof(*in6)); |
| 635 | in6->s6_addr16[0] = IPV6_ADDR_INT16_MLL; |
| 636 | in6->s6_addr8[11] = 2; |
| 637 | if (oldmcprefix == 0) { |
no test coverage detected