| 2000 | } |
| 2001 | |
| 2002 | static int |
| 2003 | unp_externalize(struct mbuf *control, struct mbuf **controlp, int flags) |
| 2004 | { |
| 2005 | struct thread *td = curthread; /* XXX */ |
| 2006 | struct cmsghdr *cm = mtod(control, struct cmsghdr *); |
| 2007 | int i; |
| 2008 | int *fdp; |
| 2009 | struct filedesc *fdesc = td->td_proc->p_fd; |
| 2010 | struct filedescent **fdep; |
| 2011 | void *data; |
| 2012 | socklen_t clen = control->m_len, datalen; |
| 2013 | int error, newfds; |
| 2014 | u_int newlen; |
| 2015 | |
| 2016 | UNP_LINK_UNLOCK_ASSERT(); |
| 2017 | |
| 2018 | error = 0; |
| 2019 | if (controlp != NULL) /* controlp == NULL => free control messages */ |
| 2020 | *controlp = NULL; |
| 2021 | while (cm != NULL) { |
| 2022 | if (sizeof(*cm) > clen || cm->cmsg_len > clen) { |
| 2023 | error = EINVAL; |
| 2024 | break; |
| 2025 | } |
| 2026 | data = CMSG_DATA(cm); |
| 2027 | datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; |
| 2028 | if (cm->cmsg_level == SOL_SOCKET |
| 2029 | && cm->cmsg_type == SCM_RIGHTS) { |
| 2030 | newfds = datalen / sizeof(*fdep); |
| 2031 | if (newfds == 0) |
| 2032 | goto next; |
| 2033 | fdep = data; |
| 2034 | |
| 2035 | /* If we're not outputting the descriptors free them. */ |
| 2036 | if (error || controlp == NULL) { |
| 2037 | unp_freerights(fdep, newfds); |
| 2038 | goto next; |
| 2039 | } |
| 2040 | FILEDESC_XLOCK(fdesc); |
| 2041 | |
| 2042 | /* |
| 2043 | * Now change each pointer to an fd in the global |
| 2044 | * table to an integer that is the index to the local |
| 2045 | * fd table entry that we set up to point to the |
| 2046 | * global one we are transferring. |
| 2047 | */ |
| 2048 | newlen = newfds * sizeof(int); |
| 2049 | *controlp = sbcreatecontrol(NULL, newlen, |
| 2050 | SCM_RIGHTS, SOL_SOCKET); |
| 2051 | if (*controlp == NULL) { |
| 2052 | FILEDESC_XUNLOCK(fdesc); |
| 2053 | error = E2BIG; |
| 2054 | unp_freerights(fdep, newfds); |
| 2055 | goto next; |
| 2056 | } |
| 2057 | |
| 2058 | fdp = (int *) |
| 2059 | CMSG_DATA(mtod(*controlp, struct cmsghdr *)); |
nothing calls this directly
no test coverage detected