* Allocate a PCB and associate it with the socket. * On success return with the PCB locked. */
| 578 | * On success return with the PCB locked. |
| 579 | */ |
| 580 | int |
| 581 | in_pcballoc(struct socket *so, struct inpcbinfo *pcbinfo) |
| 582 | { |
| 583 | struct inpcb *inp; |
| 584 | int error; |
| 585 | |
| 586 | error = 0; |
| 587 | inp = uma_zalloc(pcbinfo->ipi_zone, M_NOWAIT); |
| 588 | if (inp == NULL) |
| 589 | return (ENOBUFS); |
| 590 | bzero(&inp->inp_start_zero, inp_zero_size); |
| 591 | #ifdef NUMA |
| 592 | inp->inp_numa_domain = M_NODOM; |
| 593 | #endif |
| 594 | inp->inp_pcbinfo = pcbinfo; |
| 595 | inp->inp_socket = so; |
| 596 | inp->inp_cred = crhold(so->so_cred); |
| 597 | inp->inp_inc.inc_fibnum = so->so_fibnum; |
| 598 | #ifdef MAC |
| 599 | error = mac_inpcb_init(inp, M_NOWAIT); |
| 600 | if (error != 0) |
| 601 | goto out; |
| 602 | mac_inpcb_create(so, inp); |
| 603 | #endif |
| 604 | #if defined(IPSEC) || defined(IPSEC_SUPPORT) |
| 605 | error = ipsec_init_pcbpolicy(inp); |
| 606 | if (error != 0) { |
| 607 | #ifdef MAC |
| 608 | mac_inpcb_destroy(inp); |
| 609 | #endif |
| 610 | goto out; |
| 611 | } |
| 612 | #endif /*IPSEC*/ |
| 613 | #ifdef INET6 |
| 614 | if (INP_SOCKAF(so) == AF_INET6) { |
| 615 | inp->inp_vflag |= INP_IPV6PROTO; |
| 616 | if (V_ip6_v6only) |
| 617 | inp->inp_flags |= IN6P_IPV6_V6ONLY; |
| 618 | } |
| 619 | #endif |
| 620 | INP_WLOCK(inp); |
| 621 | INP_LIST_WLOCK(pcbinfo); |
| 622 | CK_LIST_INSERT_HEAD(pcbinfo->ipi_listhead, inp, inp_list); |
| 623 | pcbinfo->ipi_count++; |
| 624 | so->so_pcb = (caddr_t)inp; |
| 625 | #ifdef INET6 |
| 626 | if (V_ip6_auto_flowlabel) |
| 627 | inp->inp_flags |= IN6P_AUTOFLOWLABEL; |
| 628 | #endif |
| 629 | inp->inp_gencnt = ++pcbinfo->ipi_gencnt; |
| 630 | refcount_init(&inp->inp_refcount, 1); /* Reference from inpcbinfo */ |
| 631 | |
| 632 | /* |
| 633 | * Routes in inpcb's can cache L2 as well; they are guaranteed |
| 634 | * to be cleaned up. |
| 635 | */ |
| 636 | inp->inp_route.ro_flags = RT_LLE_CACHE; |
| 637 | INP_LIST_WUNLOCK(pcbinfo); |
no test coverage detected