diff --git a/sys/cam/ctl/ctl_ha.c b/sys/cam/ctl/ctl_ha.c --- a/sys/cam/ctl/ctl_ha.c +++ b/sys/cam/ctl/ctl_ha.c @@ -397,7 +397,7 @@ ctl_ha_accept(struct ha_softc *softc) { struct socket *lso, *so; - struct sockaddr *sap; + struct sockaddr_in sin = { .sin_len = sizeof(sin) }; int error; lso = softc->ha_lso; @@ -410,16 +410,11 @@ goto out; } - sap = NULL; - error = soaccept(so, &sap); + error = soaccept(so, (struct sockaddr *)&sin); if (error != 0) { printf("%s: soaccept() error %d\n", __func__, error); - if (sap != NULL) - free(sap, M_SONAME); goto out; } - if (sap != NULL) - free(sap, M_SONAME); softc->ha_so = so; ctl_ha_sock_setup(softc); return (0); diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c --- a/sys/compat/linux/linux_socket.c +++ b/sys/compat/linux/linux_socket.c @@ -1017,31 +1017,29 @@ linux_accept_common(struct thread *td, int s, l_uintptr_t addr, l_uintptr_t namelen, int flags) { - struct sockaddr *sa; + struct sockaddr_storage ss = { .ss_len = sizeof(ss) }; struct file *fp, *fp1; - int bflags, len; struct socket *so; - int error, error1; + socklen_t len; + int bflags, error, error1; bflags = 0; fp = NULL; - sa = NULL; error = linux_set_socket_flags(flags, &bflags); if (error != 0) return (error); - if (PTRIN(addr) == NULL) { - len = 0; - error = kern_accept4(td, s, NULL, NULL, bflags, NULL); - } else { + if (PTRIN(addr) != NULL) { error = copyin(PTRIN(namelen), &len, sizeof(len)); if (error != 0) return (error); if (len < 0) return (EINVAL); - error = kern_accept4(td, s, &sa, &len, bflags, &fp); - } + } else + len = 0; + + error = kern_accept4(td, s, (struct sockaddr *)&ss, bflags, &fp); /* * Translate errno values into ones used by Linux. @@ -1071,11 +1069,14 @@ return (error); } - if (len != 0) { - error = linux_copyout_sockaddr(sa, PTRIN(addr), len); - if (error == 0) - error = copyout(&len, PTRIN(namelen), - sizeof(len)); + if (PTRIN(addr) != NULL) { + len = min(ss.ss_len, len); + error = linux_copyout_sockaddr((struct sockaddr *)&ss, + PTRIN(addr), len); + if (error == 0) { + len = ss.ss_len; + error = copyout(&len, PTRIN(namelen), sizeof(len)); + } if (error != 0) { fdclose(td, fp, td->td_retval[0]); td->td_retval[0] = 0; @@ -1083,7 +1084,6 @@ } if (fp != NULL) fdrop(fp, td); - free(sa, M_SONAME); return (error); } diff --git a/sys/dev/cxgbe/iw_cxgbe/cm.c b/sys/dev/cxgbe/iw_cxgbe/cm.c --- a/sys/dev/cxgbe/iw_cxgbe/cm.c +++ b/sys/dev/cxgbe/iw_cxgbe/cm.c @@ -974,7 +974,7 @@ { struct c4iw_listen_ep *real_lep = NULL; struct c4iw_ep *new_ep = NULL; - struct sockaddr_in *remote = NULL; + struct sockaddr_storage remote = { .ss_len = sizeof(remote) }; int ret = 0; MPASS(new_so != NULL); @@ -1019,19 +1019,16 @@ new_ep->com.state = MPA_REQ_WAIT; setiwsockopt(new_so); - ret = soaccept(new_so, (struct sockaddr **)&remote); + ret = soaccept(new_so, (struct sockaddr *)&remote); if (ret != 0) { CTR4(KTR_IW_CXGBE, "%s:listen sock:%p, new sock:%p, ret:%d", __func__, master_lep->com.so, new_so, ret); - if (remote != NULL) - free(remote, M_SONAME); soclose(new_so); c4iw_put_ep(&new_ep->com); c4iw_put_ep(&real_lep->com); return; } - free(remote, M_SONAME); START_EP_TIMER(new_ep); diff --git a/sys/dev/hyperv/hvsock/hv_sock.h b/sys/dev/hyperv/hvsock/hv_sock.h --- a/sys/dev/hyperv/hvsock/hv_sock.h +++ b/sys/dev/hyperv/hvsock/hv_sock.h @@ -100,7 +100,7 @@ int hvs_trans_attach(struct socket *, int, struct thread *); int hvs_trans_bind(struct socket *, struct sockaddr *, struct thread *); int hvs_trans_listen(struct socket *, int, struct thread *); -int hvs_trans_accept(struct socket *, struct sockaddr **); +int hvs_trans_accept(struct socket *, struct sockaddr *); int hvs_trans_connect(struct socket *, struct sockaddr *, struct thread *); int hvs_trans_peeraddr(struct socket *, struct sockaddr **); diff --git a/sys/dev/hyperv/hvsock/hv_sock.c b/sys/dev/hyperv/hvsock/hv_sock.c --- a/sys/dev/hyperv/hvsock/hv_sock.c +++ b/sys/dev/hyperv/hvsock/hv_sock.c @@ -479,7 +479,7 @@ } int -hvs_trans_accept(struct socket *so, struct sockaddr **nam) +hvs_trans_accept(struct socket *so, struct sockaddr *sa) { struct hvs_pcb *pcb = so2hvspcb(so); @@ -489,10 +489,9 @@ if (pcb == NULL) return (EINVAL); - *nam = sodupsockaddr((struct sockaddr *) &pcb->remote_addr, - M_NOWAIT); + memcpy(sa, &pcb->remote_addr, pcb->remote_addr.sa_len); - return ((*nam == NULL) ? ENOMEM : 0); + return (0); } int diff --git a/sys/dev/iscsi/icl_soft_proxy.c b/sys/dev/iscsi/icl_soft_proxy.c --- a/sys/dev/iscsi/icl_soft_proxy.c +++ b/sys/dev/iscsi/icl_soft_proxy.c @@ -208,7 +208,7 @@ { struct icl_listen_sock *ils; struct socket *head, *so; - struct sockaddr *sa; + struct sockaddr_storage ss = { .ss_len = sizeof(ss) }; int error; ils = arg; @@ -234,17 +234,15 @@ continue; } - sa = NULL; - error = soaccept(so, &sa); + error = soaccept(so, (struct sockaddr *)&ss); if (error != 0) { ICL_WARN("soaccept error %d", error); - if (sa != NULL) - free(sa, M_SONAME); soclose(so); continue; } - (ils->ils_listen->il_accept)(so, sa, ils->ils_id); + (ils->ils_listen->il_accept)(so, (struct sockaddr *)&ss, + ils->ils_id); } } diff --git a/sys/kern/uipc_domain.c b/sys/kern/uipc_domain.c --- a/sys/kern/uipc_domain.c +++ b/sys/kern/uipc_domain.c @@ -56,7 +56,7 @@ MTX_SYSINIT(domain, &dom_mtx, "domain list", MTX_DEF); static int -pr_accept_notsupp(struct socket *so, struct sockaddr **nam) +pr_accept_notsupp(struct socket *so, struct sockaddr *sa) { return (EOPNOTSUPP); } diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1350,12 +1350,17 @@ } int -soaccept(struct socket *so, struct sockaddr **nam) +soaccept(struct socket *so, struct sockaddr *sa) { +#ifdef INVARIANTS + u_char len = sa->sa_len; +#endif int error; CURVNET_SET(so->so_vnet); - error = so->so_proto->pr_accept(so, nam); + error = so->so_proto->pr_accept(so, sa); + KASSERT(sa->sa_len <= len, + ("%s: protocol %p sockaddr overflow", __func__, so->so_proto)); CURVNET_RESTORE(); return (error); } diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -279,19 +279,18 @@ accept1(struct thread *td, int s, struct sockaddr *uname, socklen_t *anamelen, int flags) { - struct sockaddr *name; - socklen_t namelen; + struct sockaddr_storage ss = { .ss_len = sizeof(ss) }; + socklen_t addrlen; struct file *fp; int error; - if (uname == NULL) - return (kern_accept4(td, s, NULL, NULL, flags, NULL)); - - error = copyin(anamelen, &namelen, sizeof (namelen)); - if (error != 0) - return (error); + if (uname != NULL) { + error = copyin(anamelen, &addrlen, sizeof(addrlen)); + if (error != 0) + return (error); + } - error = kern_accept4(td, s, &name, &namelen, flags, &fp); + error = kern_accept4(td, s, (struct sockaddr *)&ss, flags, &fp); if (error != 0) return (error); @@ -299,42 +298,40 @@ #ifdef COMPAT_OLDSOCK if (SV_PROC_FLAG(td->td_proc, SV_AOUT) && (flags & ACCEPT4_COMPAT) != 0) - ((struct osockaddr *)name)->sa_family = - name->sa_family; + ((struct osockaddr *)&ss)->sa_family = ss.ss_family; #endif - error = copyout(name, uname, namelen); - if (error == 0) - error = copyout(&namelen, anamelen, - sizeof(namelen)); + if (uname != NULL) { + addrlen = min(ss.ss_len, addrlen); + error = copyout(&ss, uname, addrlen); + if (error == 0) { + addrlen = ss.ss_len; + error = copyout(&addrlen, anamelen, sizeof(addrlen)); + } + } if (error != 0) fdclose(td, fp, td->td_retval[0]); fdrop(fp, td); - free(name, M_SONAME); + return (error); } int -kern_accept(struct thread *td, int s, struct sockaddr **name, - socklen_t *namelen, struct file **fp) +kern_accept(struct thread *td, int s, struct sockaddr *sa, struct file **fp) { - return (kern_accept4(td, s, name, namelen, ACCEPT4_INHERIT, fp)); + return (kern_accept4(td, s, sa, ACCEPT4_INHERIT, fp)); } int -kern_accept4(struct thread *td, int s, struct sockaddr **name, - socklen_t *namelen, int flags, struct file **fp) +kern_accept4(struct thread *td, int s, struct sockaddr *sa, int flags, + struct file **fp) { struct file *headfp, *nfp = NULL; - struct sockaddr *sa = NULL; struct socket *head, *so; struct filecaps fcaps; u_int fflag; pid_t pgid; int error, fd, tmp; - if (name != NULL) - *name = NULL; - AUDIT_ARG_FD(s); error = getsock_cap(td, s, &cap_accept_rights, &headfp, &fcaps); @@ -388,29 +385,15 @@ (void) fo_ioctl(nfp, FIONBIO, &tmp, td->td_ucred, td); tmp = fflag & FASYNC; (void) fo_ioctl(nfp, FIOASYNC, &tmp, td->td_ucred, td); - error = soaccept(so, &sa); - if (error != 0) - goto noconnection; - if (sa == NULL) { - if (name) - *namelen = 0; - goto done; - } - AUDIT_ARG_SOCKADDR(td, AT_FDCWD, sa); - if (name) { - /* check sa_len before it is destroyed */ - if (*namelen > sa->sa_len) - *namelen = sa->sa_len; + + if ((error = soaccept(so, sa)) == 0) { + AUDIT_ARG_SOCKADDR(td, AT_FDCWD, sa); #ifdef KTRACE if (KTRPOINT(td, KTR_STRUCT)) ktrsockaddr(sa); #endif - *name = sa; - sa = NULL; } noconnection: - free(sa, M_SONAME); - /* * close the new descriptor, assuming someone hasn't ripped it * out from under us. diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -122,7 +122,10 @@ static SLIST_HEAD(, unp_defer) unp_defers; static int unp_defers_count; -static const struct sockaddr sun_noname = { sizeof(sun_noname), AF_LOCAL }; +static const struct sockaddr sun_noname = { + .sa_len = sizeof(sun_noname), + .sa_family = AF_LOCAL, +}; /* * Garbage collection of cyclic file descriptor/socket references occurs @@ -436,7 +439,7 @@ } static int -uipc_accept(struct socket *so, struct sockaddr **nam) +uipc_accept(struct socket *so, struct sockaddr *ret) { struct unpcb *unp, *unp2; const struct sockaddr *sa; @@ -448,14 +451,13 @@ unp = sotounpcb(so); KASSERT(unp != NULL, ("uipc_accept: unp == NULL")); - *nam = malloc(sizeof(struct sockaddr_un), M_SONAME, M_WAITOK); UNP_PCB_LOCK(unp); unp2 = unp_pcb_lock_peer(unp); if (unp2 != NULL && unp2->unp_addr != NULL) sa = (struct sockaddr *)unp2->unp_addr; else sa = &sun_noname; - bcopy(sa, *nam, sa->sa_len); + bcopy(sa, ret, sa->sa_len); if (unp2 != NULL) unp_pcb_unlock_pair(unp, unp2); else diff --git a/sys/netgraph/bluetooth/include/ng_btsocket_l2cap.h b/sys/netgraph/bluetooth/include/ng_btsocket_l2cap.h --- a/sys/netgraph/bluetooth/include/ng_btsocket_l2cap.h +++ b/sys/netgraph/bluetooth/include/ng_btsocket_l2cap.h @@ -191,7 +191,7 @@ void ng_btsocket_l2cap_abort (struct socket *); void ng_btsocket_l2cap_close (struct socket *); -int ng_btsocket_l2cap_accept (struct socket *, struct sockaddr **); +int ng_btsocket_l2cap_accept (struct socket *, struct sockaddr *); int ng_btsocket_l2cap_attach (struct socket *, int, struct thread *); int ng_btsocket_l2cap_bind (struct socket *, struct sockaddr *, struct thread *); diff --git a/sys/netgraph/bluetooth/include/ng_btsocket_rfcomm.h b/sys/netgraph/bluetooth/include/ng_btsocket_rfcomm.h --- a/sys/netgraph/bluetooth/include/ng_btsocket_rfcomm.h +++ b/sys/netgraph/bluetooth/include/ng_btsocket_rfcomm.h @@ -316,7 +316,7 @@ void ng_btsocket_rfcomm_abort (struct socket *); void ng_btsocket_rfcomm_close (struct socket *); -int ng_btsocket_rfcomm_accept (struct socket *, struct sockaddr **); +int ng_btsocket_rfcomm_accept (struct socket *, struct sockaddr *); int ng_btsocket_rfcomm_attach (struct socket *, int, struct thread *); int ng_btsocket_rfcomm_bind (struct socket *, struct sockaddr *, struct thread *); diff --git a/sys/netgraph/bluetooth/include/ng_btsocket_sco.h b/sys/netgraph/bluetooth/include/ng_btsocket_sco.h --- a/sys/netgraph/bluetooth/include/ng_btsocket_sco.h +++ b/sys/netgraph/bluetooth/include/ng_btsocket_sco.h @@ -106,7 +106,7 @@ void ng_btsocket_sco_abort (struct socket *); void ng_btsocket_sco_close (struct socket *); -int ng_btsocket_sco_accept (struct socket *, struct sockaddr **); +int ng_btsocket_sco_accept (struct socket *, struct sockaddr *); int ng_btsocket_sco_attach (struct socket *, int, struct thread *); int ng_btsocket_sco_bind (struct socket *, struct sockaddr *, struct thread *); diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c b/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c --- a/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c +++ b/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c @@ -1967,20 +1967,6 @@ (void)ng_btsocket_l2cap_disconnect(so); } /* ng_btsocket_l2cap_close */ -/* - * Accept connection on socket. Nothing to do here, socket must be connected - * and ready, so just return peer address and be done with it. - */ - -int -ng_btsocket_l2cap_accept(struct socket *so, struct sockaddr **nam) -{ - if (ng_btsocket_l2cap_node == NULL) - return (EINVAL); - - return (ng_btsocket_l2cap_peeraddr(so, nam)); -} /* ng_btsocket_l2cap_accept */ - /* * Create and attach new socket */ @@ -2523,41 +2509,67 @@ return (error); } /* ng_btsocket_listen */ -/* - * Get peer address - */ - -int -ng_btsocket_l2cap_peeraddr(struct socket *so, struct sockaddr **nam) +static int +ng_btsocket_l2cap_peeraddr1(struct socket *so, struct sockaddr_l2cap *sa) { ng_btsocket_l2cap_pcb_p pcb = so2l2cap_pcb(so); - struct sockaddr_l2cap sa; if (pcb == NULL) return (EINVAL); if (ng_btsocket_l2cap_node == NULL) return (EINVAL); - bcopy(&pcb->dst, &sa.l2cap_bdaddr, sizeof(sa.l2cap_bdaddr)); - sa.l2cap_psm = htole16(pcb->psm); - sa.l2cap_len = sizeof(sa); - sa.l2cap_family = AF_BLUETOOTH; + *sa = (struct sockaddr_l2cap ){ + .l2cap_len = sizeof(struct sockaddr_l2cap), + .l2cap_family = AF_BLUETOOTH, + .l2cap_psm = htole16(pcb->psm), + }; + bcopy(&pcb->dst, &sa->l2cap_bdaddr, sizeof(sa->l2cap_bdaddr)); switch(pcb->idtype){ case NG_L2CAP_L2CA_IDTYPE_ATT: - sa.l2cap_cid = NG_L2CAP_ATT_CID; + sa->l2cap_cid = NG_L2CAP_ATT_CID; break; case NG_L2CAP_L2CA_IDTYPE_SMP: - sa.l2cap_cid = NG_L2CAP_SMP_CID; + sa->l2cap_cid = NG_L2CAP_SMP_CID; break; default: - sa.l2cap_cid = 0; + sa->l2cap_cid = 0; break; } - sa.l2cap_bdaddr_type = pcb->dsttype; + sa->l2cap_bdaddr_type = pcb->dsttype; + + return (0); +} + +/* + * Get peer address + */ +int +ng_btsocket_l2cap_peeraddr(struct socket *so, struct sockaddr **nam) +{ + struct sockaddr_l2cap sa; + int error; + + error = ng_btsocket_l2cap_peeraddr1(so, &sa); + if (error != 0) + return (error); *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT); return ((*nam == NULL)? ENOMEM : 0); -} /* ng_btsocket_l2cap_peeraddr */ +} + +/* + * Accept connection on socket. Nothing to do here, socket must be connected + * and ready, so just return peer address and be done with it. + */ +int +ng_btsocket_l2cap_accept(struct socket *so, struct sockaddr *sa) +{ + if (ng_btsocket_l2cap_node == NULL) + return (EINVAL); + + return (ng_btsocket_l2cap_peeraddr1(so, (struct sockaddr_l2cap *)sa)); +} /* * Send data to socket diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c b/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c --- a/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c +++ b/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c @@ -370,17 +370,6 @@ (void)ng_btsocket_rfcomm_disconnect(so); } /* ng_btsocket_rfcomm_close */ -/* - * Accept connection on socket. Nothing to do here, socket must be connected - * and ready, so just return peer address and be done with it. - */ - -int -ng_btsocket_rfcomm_accept(struct socket *so, struct sockaddr **nam) -{ - return (ng_btsocket_rfcomm_peeraddr(so, nam)); -} /* ng_btsocket_rfcomm_accept */ - /* * Create and attach new socket */ @@ -925,28 +914,51 @@ return (error); } /* ng_btsocket_listen */ -/* - * Get peer address - */ - -int -ng_btsocket_rfcomm_peeraddr(struct socket *so, struct sockaddr **nam) +static int +ng_btsocket_rfcomm_peeraddr1(struct socket *so, struct sockaddr_rfcomm *sa) { ng_btsocket_rfcomm_pcb_p pcb = so2rfcomm_pcb(so); - struct sockaddr_rfcomm sa; if (pcb == NULL) return (EINVAL); - bcopy(&pcb->dst, &sa.rfcomm_bdaddr, sizeof(sa.rfcomm_bdaddr)); - sa.rfcomm_channel = pcb->channel; - sa.rfcomm_len = sizeof(sa); - sa.rfcomm_family = AF_BLUETOOTH; + *sa = (struct sockaddr_rfcomm ){ + .rfcomm_len = sizeof(struct sockaddr_rfcomm), + .rfcomm_family = AF_BLUETOOTH, + .rfcomm_channel = pcb->channel, + }; + bcopy(&pcb->dst, &sa->rfcomm_bdaddr, sizeof(sa->rfcomm_bdaddr)); + return (0); +} + +/* + * Get peer address + */ +int +ng_btsocket_rfcomm_peeraddr(struct socket *so, struct sockaddr **nam) +{ + struct sockaddr_rfcomm sa; + int error; + + error = ng_btsocket_rfcomm_peeraddr1(so, &sa); + if (error != 0) + return (error); *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT); return ((*nam == NULL)? ENOMEM : 0); -} /* ng_btsocket_rfcomm_peeraddr */ +} + +/* + * Accept connection on socket. Nothing to do here, socket must be connected + * and ready, so just return peer address and be done with it. + */ +int +ng_btsocket_rfcomm_accept(struct socket *so, struct sockaddr *sa) +{ + + return (ng_btsocket_rfcomm_peeraddr1(so, (struct sockaddr_rfcomm *)sa)); +} /* * Send data to socket @@ -1407,7 +1419,7 @@ ng_btsocket_rfcomm_session_accept(ng_btsocket_rfcomm_session_p s0) { struct socket *l2so; - struct sockaddr_l2cap *l2sa = NULL; + struct sockaddr_l2cap l2sa = { .l2cap_len = sizeof(l2sa) }; ng_btsocket_l2cap_pcb_t *l2pcb = NULL; ng_btsocket_rfcomm_session_p s = NULL; int error; @@ -1425,7 +1437,7 @@ return (error); } - error = soaccept(l2so, (struct sockaddr **) &l2sa); + error = soaccept(l2so, (struct sockaddr *)&l2sa); if (error != 0) { NG_BTSOCKET_RFCOMM_ERR( "%s: soaccept() on L2CAP socket failed, error=%d\n", __func__, error); diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_sco.c b/sys/netgraph/bluetooth/socket/ng_btsocket_sco.c --- a/sys/netgraph/bluetooth/socket/ng_btsocket_sco.c +++ b/sys/netgraph/bluetooth/socket/ng_btsocket_sco.c @@ -1176,20 +1176,6 @@ (void) ng_btsocket_sco_disconnect(so); } /* ng_btsocket_sco_close */ -/* - * Accept connection on socket. Nothing to do here, socket must be connected - * and ready, so just return peer address and be done with it. - */ - -int -ng_btsocket_sco_accept(struct socket *so, struct sockaddr **nam) -{ - if (ng_btsocket_sco_node == NULL) - return (EINVAL); - - return (ng_btsocket_sco_peeraddr(so, nam)); -} /* ng_btsocket_sco_accept */ - /* * Create and attach new socket */ @@ -1623,32 +1609,56 @@ return (error); } /* ng_btsocket_listen */ -/* - * Get peer address - */ - -int -ng_btsocket_sco_peeraddr(struct socket *so, struct sockaddr **nam) +static int +ng_btsocket_sco_peeraddr1(struct socket *so, struct sockaddr_sco *sa) { ng_btsocket_sco_pcb_p pcb = so2sco_pcb(so); - struct sockaddr_sco sa; if (pcb == NULL) return (EINVAL); if (ng_btsocket_sco_node == NULL) return (EINVAL); + *sa = (struct sockaddr_sco ){ + .sco_len = sizeof(struct sockaddr_sco), + .sco_family = AF_BLUETOOTH, + }; mtx_lock(&pcb->pcb_mtx); - bcopy(&pcb->dst, &sa.sco_bdaddr, sizeof(sa.sco_bdaddr)); + bcopy(&pcb->dst, &sa->sco_bdaddr, sizeof(sa->sco_bdaddr)); mtx_unlock(&pcb->pcb_mtx); - sa.sco_len = sizeof(sa); - sa.sco_family = AF_BLUETOOTH; + return (0); +} + +/* + * Get peer address + */ +int +ng_btsocket_sco_peeraddr(struct socket *so, struct sockaddr **nam) +{ + struct sockaddr_sco sa; + int error; + error = ng_btsocket_sco_peeraddr1(so, &sa); + if (error != 0) + return (error); *nam = sodupsockaddr((struct sockaddr *) &sa, M_NOWAIT); return ((*nam == NULL)? ENOMEM : 0); -} /* ng_btsocket_sco_peeraddr */ +} + +/* + * Accept connection on socket. Nothing to do here, socket must be connected + * and ready, so just return peer address and be done with it. + */ +int +ng_btsocket_sco_accept(struct socket *so, struct sockaddr *sa) +{ + if (ng_btsocket_sco_node == NULL) + return (EINVAL); + + return (ng_btsocket_sco_peeraddr1(so, (struct sockaddr_sco *)sa)); +} /* * Send data to socket diff --git a/sys/netgraph/ng_ksocket.c b/sys/netgraph/ng_ksocket.c --- a/sys/netgraph/ng_ksocket.c +++ b/sys/netgraph/ng_ksocket.c @@ -1178,7 +1178,7 @@ { struct socket *const head = priv->so; struct socket *so; - struct sockaddr *sa = NULL; + struct sockaddr_storage ss = { .ss_len = sizeof(ss) }; struct ng_mesg *resp; struct ng_ksocket_accept *resp_data; node_p node; @@ -1196,12 +1196,11 @@ if (error) return (error); - if ((error = soaccept(so, &sa)) != 0) + if ((error = soaccept(so, (struct sockaddr *)&ss)) != 0) return (error); len = OFFSETOF(struct ng_ksocket_accept, addr); - if (sa != NULL) - len += sa->sa_len; + len += ss.ss_len; NG_MKMESSAGE(resp, NGM_KSOCKET_COOKIE, NGM_KSOCKET_ACCEPT, len, M_NOWAIT); @@ -1249,13 +1248,10 @@ /* Fill in the response data and send it or return it to the caller */ resp_data = (struct ng_ksocket_accept *)resp->data; resp_data->nodeid = NG_NODE_ID(node); - if (sa != NULL) - bcopy(sa, &resp_data->addr, sa->sa_len); + bcopy(&ss, &resp_data->addr, ss.ss_len); NG_SEND_MSG_ID(error, node, resp, priv->response_addr, 0); out: - if (sa != NULL) - free(sa, M_SONAME); return (0); } diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -7271,7 +7271,7 @@ static int sctp_defered_wakeup_cnt = 0; int -sctp_accept(struct socket *so, struct sockaddr **addr) +sctp_accept(struct socket *so, struct sockaddr *sa) { struct sctp_tcb *stcb; struct sctp_inpcb *inp; @@ -7338,39 +7338,25 @@ switch (store.sa.sa_family) { #ifdef INET case AF_INET: - { - struct sockaddr_in *sin; - - SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin); - if (sin == NULL) - return (ENOMEM); - sin->sin_family = AF_INET; - sin->sin_len = sizeof(*sin); - sin->sin_port = store.sin.sin_port; - sin->sin_addr = store.sin.sin_addr; - *addr = (struct sockaddr *)sin; - break; - } + *(struct sockaddr_in *)sa = (struct sockaddr_in ){ + .sin_family = AF_INET, + .sin_len = sizeof(struct sockaddr_in), + .sin_port = store.sin.sin_port, + .sin_addr = store.sin.sin_addr, + }; + break; #endif #ifdef INET6 case AF_INET6: - { - struct sockaddr_in6 *sin6; - - SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6); - if (sin6 == NULL) - return (ENOMEM); - sin6->sin6_family = AF_INET6; - sin6->sin6_len = sizeof(*sin6); - sin6->sin6_port = store.sin6.sin6_port; - sin6->sin6_addr = store.sin6.sin6_addr; - if ((error = sa6_recoverscope(sin6)) != 0) { - SCTP_FREE_SONAME(sin6); - return (error); - } - *addr = (struct sockaddr *)sin6; - break; - } + *(struct sockaddr_in6 *)sa = (struct sockaddr_in6 ){ + .sin6_family = AF_INET6, + .sin6_len = sizeof(struct sockaddr_in6), + .sin6_port = store.sin6.sin6_port, + .sin6_addr = store.sin6.sin6_addr, + }; + if ((error = sa6_recoverscope((struct sockaddr_in6 *)sa)) != 0) + return (error); + break; #endif default: /* TSNH */ diff --git a/sys/netinet/sctp_var.h b/sys/netinet/sctp_var.h --- a/sys/netinet/sctp_var.h +++ b/sys/netinet/sctp_var.h @@ -341,7 +341,7 @@ int sctp_ingetaddr(struct socket *, struct sockaddr **); int sctp_peeraddr(struct socket *, struct sockaddr **); int sctp_listen(struct socket *, int, struct thread *); -int sctp_accept(struct socket *, struct sockaddr **); +int sctp_accept(struct socket *, struct sockaddr *); #endif /* _KERNEL */ diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -719,13 +719,11 @@ * just return the address of the peer, storing through addr. */ static int -tcp_usr_accept(struct socket *so, struct sockaddr **nam) +tcp_usr_accept(struct socket *so, struct sockaddr *sa) { - int error = 0; struct inpcb *inp; struct tcpcb *tp; - struct in_addr addr; - in_port_t port = 0; + int error = 0; inp = sotoinpcb(so); KASSERT(inp != NULL, ("tcp_usr_accept: inp == NULL")); @@ -736,39 +734,30 @@ } tp = intotcpcb(inp); - if (so->so_state & SS_ISDISCONNECTED) { + if (so->so_state & SS_ISDISCONNECTED) error = ECONNABORTED; - goto out; - } - /* - * We inline in_getpeeraddr and COMMON_END here, so that we can - * copy the data of interest and defer the malloc until after we - * release the lock. - */ - port = inp->inp_fport; - addr = inp->inp_faddr; - -out: + else + *(struct sockaddr_in *)sa = (struct sockaddr_in ){ + .sin_family = AF_INET, + .sin_len = sizeof(struct sockaddr_in), + .sin_port = inp->inp_fport, + .sin_addr = inp->inp_faddr, + }; tcp_bblog_pru(tp, PRU_ACCEPT, error); TCP_PROBE2(debug__user, tp, PRU_ACCEPT); INP_WUNLOCK(inp); - if (error == 0) - *nam = in_sockaddr(port, &addr); - return error; + + return (error); } #endif /* INET */ #ifdef INET6 static int -tcp6_usr_accept(struct socket *so, struct sockaddr **nam) +tcp6_usr_accept(struct socket *so, struct sockaddr *sa) { struct inpcb *inp; - int error = 0; struct tcpcb *tp; - struct in_addr addr; - struct in6_addr addr6; - in_port_t port = 0; - int v4 = 0; + int error = 0; inp = sotoinpcb(so); KASSERT(inp != NULL, ("tcp6_usr_accept: inp == NULL")); @@ -781,33 +770,32 @@ if (so->so_state & SS_ISDISCONNECTED) { error = ECONNABORTED; - goto out; - } - /* - * We inline in6_mapped_peeraddr and COMMON_END here, so that we can - * copy the data of interest and defer the malloc until after we - * release the lock. - */ - if (inp->inp_vflag & INP_IPV4) { - v4 = 1; - port = inp->inp_fport; - addr = inp->inp_faddr; } else { - port = inp->inp_fport; - addr6 = inp->in6p_faddr; + if (inp->inp_vflag & INP_IPV4) { + struct sockaddr_in sin = { + .sin_family = AF_INET, + .sin_len = sizeof(struct sockaddr_in), + .sin_port = inp->inp_fport, + .sin_addr = inp->inp_faddr, + }; + in6_sin_2_v4mapsin6(&sin, (struct sockaddr_in6 *)sa); + } else { + *(struct sockaddr_in6 *)sa = (struct sockaddr_in6 ){ + .sin6_family = AF_INET6, + .sin6_len = sizeof(struct sockaddr_in6), + .sin6_port = inp->inp_fport, + .sin6_addr = inp->in6p_faddr, + }; + /* XXX: should catch errors */ + (void)sa6_recoverscope((struct sockaddr_in6 *)sa); + } } -out: tcp_bblog_pru(tp, PRU_ACCEPT, error); TCP_PROBE2(debug__user, tp, PRU_ACCEPT); INP_WUNLOCK(inp); - if (error == 0) { - if (v4) - *nam = in6_v4mapsin6_sockaddr(port, &addr); - else - *nam = in6_sockaddr(port, &addr6); - } - return error; + + return (error); } #endif /* INET6 */ diff --git a/sys/netinet6/in6_pcb.h b/sys/netinet6/in6_pcb.h --- a/sys/netinet6/in6_pcb.h +++ b/sys/netinet6/in6_pcb.h @@ -100,8 +100,6 @@ in6_rtchange(struct inpcb *, int); struct sockaddr * in6_sockaddr(in_port_t port, struct in6_addr *addr_p); -struct sockaddr * - in6_v4mapsin6_sockaddr(in_port_t port, struct in_addr *addr_p); int in6_getpeeraddr(struct socket *so, struct sockaddr **nam); int in6_getsockaddr(struct socket *so, struct sockaddr **nam); int in6_mapped_sockaddr(struct socket *so, struct sockaddr **nam); diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c --- a/sys/netinet6/in6_pcb.c +++ b/sys/netinet6/in6_pcb.c @@ -519,25 +519,6 @@ return (struct sockaddr *)sin6; } -struct sockaddr * -in6_v4mapsin6_sockaddr(in_port_t port, struct in_addr *addr_p) -{ - struct sockaddr_in sin; - struct sockaddr_in6 *sin6_p; - - bzero(&sin, sizeof sin); - sin.sin_family = AF_INET; - sin.sin_len = sizeof(sin); - sin.sin_port = port; - sin.sin_addr = *addr_p; - - sin6_p = malloc(sizeof *sin6_p, M_SONAME, - M_WAITOK); - in6_sin_2_v4mapsin6(&sin, sin6_p); - - return (struct sockaddr *)sin6_p; -} - int in6_getsockaddr(struct socket *so, struct sockaddr **nam) { diff --git a/sys/ofed/drivers/infiniband/ulp/sdp/sdp_main.c b/sys/ofed/drivers/infiniband/ulp/sdp/sdp_main.c --- a/sys/ofed/drivers/infiniband/ulp/sdp/sdp_main.c +++ b/sys/ofed/drivers/infiniband/ulp/sdp/sdp_main.c @@ -776,32 +776,29 @@ * are fully initialized. */ static int -sdp_accept(struct socket *so, struct sockaddr **nam) +sdp_accept(struct socket *so, struct sockaddr *sa) { struct sdp_sock *ssk = NULL; - struct in_addr addr; - in_port_t port; int error; if (so->so_state & SS_ISDISCONNECTED) return (ECONNABORTED); - port = 0; - addr.s_addr = 0; error = 0; ssk = sdp_sk(so); SDP_WLOCK(ssk); - if (ssk->flags & (SDP_TIMEWAIT | SDP_DROPPED)) { + if (ssk->flags & (SDP_TIMEWAIT | SDP_DROPPED)) error = ECONNABORTED; - goto out; - } - port = ssk->fport; - addr.s_addr = ssk->faddr; -out: + else + *(struct sockaddr_in *)sa = (struct sockaddr_in ){ + .sin_family = AF_INET, + .sin_len = sizeof(struct sockaddr_in), + .sin_addr.s_addr = ssk->faddr, + .sin_port = ssk->fport, + }; SDP_WUNLOCK(ssk); - if (error == 0) - *nam = sdp_sockaddr(port, &addr); - return error; + + return (error); } /* diff --git a/sys/rpc/svc_vc.c b/sys/rpc/svc_vc.c --- a/sys/rpc/svc_vc.c +++ b/sys/rpc/svc_vc.c @@ -424,7 +424,7 @@ struct sockaddr **addrp, struct mbuf **mp) { struct socket *so = NULL; - struct sockaddr *sa = NULL; + struct sockaddr_storage ss = { .ss_len = sizeof(ss) }; int error; SVCXPRT *new_xprt; @@ -468,15 +468,12 @@ sx_xunlock(&xprt->xp_lock); - sa = NULL; - error = soaccept(so, &sa); + error = soaccept(so, (struct sockaddr *)&ss); if (error) { /* * XXX not sure if I need to call sofree or soclose here. */ - if (sa) - free(sa, M_SONAME); return (FALSE); } @@ -484,15 +481,14 @@ * svc_vc_create_conn will call xprt_register - we don't need * to do anything with the new connection except derefence it. */ - new_xprt = svc_vc_create_conn(xprt->xp_pool, so, sa); + new_xprt = svc_vc_create_conn(xprt->xp_pool, so, + (struct sockaddr *)&ss); if (!new_xprt) { soclose(so); } else { SVC_RELEASE(new_xprt); } - free(sa, M_SONAME); - return (FALSE); /* there is never an rpc msg to be processed */ } diff --git a/sys/sys/protosw.h b/sys/sys/protosw.h --- a/sys/sys/protosw.h +++ b/sys/sys/protosw.h @@ -63,7 +63,7 @@ typedef int pr_ctloutput_t(struct socket *, struct sockopt *); typedef int pr_setsbopt_t(struct socket *, struct sockopt *); typedef void pr_abort_t(struct socket *); -typedef int pr_accept_t(struct socket *, struct sockaddr **); +typedef int pr_accept_t(struct socket *, struct sockaddr *); typedef int pr_attach_t(struct socket *, int, struct thread *); typedef int pr_bind_t(struct socket *, struct sockaddr *, struct thread *); typedef int pr_connect_t(struct socket *, struct sockaddr *, diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -451,7 +451,7 @@ int getsock(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp); void soabort(struct socket *so); -int soaccept(struct socket *so, struct sockaddr **nam); +int soaccept(struct socket *so, struct sockaddr *sa); void soaio_enqueue(struct task *task); void soaio_rcv(void *context, int pending); void soaio_snd(void *context, int pending); diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h --- a/sys/sys/syscallsubr.h +++ b/sys/sys/syscallsubr.h @@ -84,10 +84,10 @@ size_t buflen, size_t path_max); int kern_abort2(struct thread *td, const char *why, int nargs, void **uargs); -int kern_accept(struct thread *td, int s, struct sockaddr **name, - socklen_t *namelen, struct file **fp); -int kern_accept4(struct thread *td, int s, struct sockaddr **name, - socklen_t *namelen, int flags, struct file **fp); +int kern_accept(struct thread *td, int s, struct sockaddr *sa, + struct file **fp); +int kern_accept4(struct thread *td, int s, struct sockaddr *sa, + int flags, struct file **fp); int kern_accessat(struct thread *td, int fd, const char *path, enum uio_seg pathseg, int flags, int mode); int kern_adjtime(struct thread *td, struct timeval *delta, diff --git a/tests/sys/kern/socket_accept.c b/tests/sys/kern/socket_accept.c --- a/tests/sys/kern/socket_accept.c +++ b/tests/sys/kern/socket_accept.c @@ -81,10 +81,7 @@ salen = 0; ATF_REQUIRE(accept(l, (struct sockaddr *)&ret, &salen) > 0); ATF_REQUIRE(memcmp(&ret, &canary, sizeof(ret)) == 0); -#if 0 - /* Linux behavior. Matches my reading of accept(2) and POSIX. */ ATF_REQUIRE(salen == sizeof(struct sockaddr_in)); -#endif /* Note: Linux will block for connection here, we fail immediately. */ ATF_REQUIRE(accept(l, (struct sockaddr *)&ret, NULL) == -1); ATF_REQUIRE(errno == EFAULT);