diff options
author | iedowse <iedowse@FreeBSD.org> | 2002-10-21 20:10:05 +0000 |
---|---|---|
committer | iedowse <iedowse@FreeBSD.org> | 2002-10-21 20:10:05 +0000 |
commit | f94a5e8a54c64c705cd34cfd49c5a5b9ee23d689 (patch) | |
tree | 48a30c5300c4af974317246dce18b075e4367190 /sys/netinet/udp_usrreq.c | |
parent | 687253b085a0885d2a22c1e4c437a522e639d9c0 (diff) | |
download | FreeBSD-src-f94a5e8a54c64c705cd34cfd49c5a5b9ee23d689.zip FreeBSD-src-f94a5e8a54c64c705cd34cfd49c5a5b9ee23d689.tar.gz |
Remove the "temporary connection" hack in udp_output(). In order
to send datagrams from an unconnected socket, we used to first block
input, then connect the socket to the sendmsg/sendto destination,
send the datagram, and finally disconnect the socket and unblock
input.
We now use in_pcbconnect_setup() to check if a connect() would have
succeeded, but we never record the connection in the PCB (local
anonymous port allocation is still recorded, though). The result
from in_pcbconnect_setup() authorises the sending of the datagram
and selects the local address and port to use, so we just construct
the header and call ip_output().
Discussed on: -net
Approved by: re
Diffstat (limited to 'sys/netinet/udp_usrreq.c')
-rw-r--r-- | sys/netinet/udp_usrreq.c | 49 |
1 files changed, 26 insertions, 23 deletions
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 03ed875..263a92e 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -688,9 +688,10 @@ udp_output(inp, m, addr, control, td) { register struct udpiphdr *ui; register int len = m->m_pkthdr.len; - struct in_addr laddr; + struct in_addr faddr, laddr; struct sockaddr_in *sin; - int s = 0, error = 0; + int error = 0; + u_short fport, lport; #ifdef MAC mac_create_mbuf_from_socket(inp->inp_socket, m); @@ -704,26 +705,36 @@ udp_output(inp, m, addr, control, td) goto release; } + laddr = inp->inp_laddr; + lport = inp->inp_lport; if (addr) { sin = (struct sockaddr_in *)addr; if (td && jailed(td->td_ucred)) prison_remote_ip(td->td_ucred, 0, &sin->sin_addr.s_addr); - laddr = inp->inp_laddr; if (inp->inp_faddr.s_addr != INADDR_ANY) { error = EISCONN; goto release; } - /* - * Must block input while temporarily connected. - */ - s = splnet(); - error = in_pcbconnect(inp, addr, td); - if (error) { - splx(s); + error = in_pcbconnect_setup(inp, addr, &laddr.s_addr, &lport, + &faddr.s_addr, &fport, NULL, td); + if (error) goto release; + + /* Commit the local port if newly assigned. */ + if (inp->inp_laddr.s_addr == INADDR_ANY && + inp->inp_lport == 0) { + inp->inp_lport = lport; + if (in_pcbinshash(inp) != 0) { + inp->inp_lport = 0; + error = EAGAIN; + goto release; + } + inp->inp_flags |= INP_ANONPORT; } } else { - if (inp->inp_faddr.s_addr == INADDR_ANY) { + faddr = inp->inp_faddr; + fport = inp->inp_fport; + if (faddr.s_addr == INADDR_ANY) { error = ENOTCONN; goto release; } @@ -735,8 +746,6 @@ udp_output(inp, m, addr, control, td) M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT); if (m == 0) { error = ENOBUFS; - if (addr) - splx(s); goto release; } @@ -747,10 +756,10 @@ udp_output(inp, m, addr, control, td) ui = mtod(m, struct udpiphdr *); bzero(ui->ui_x1, sizeof(ui->ui_x1)); /* XXX still needed? */ ui->ui_pr = IPPROTO_UDP; - ui->ui_src = inp->inp_laddr; - ui->ui_dst = inp->inp_faddr; - ui->ui_sport = inp->inp_lport; - ui->ui_dport = inp->inp_fport; + ui->ui_src = laddr; + ui->ui_dst = faddr; + ui->ui_sport = lport; + ui->ui_dport = fport; ui->ui_ulen = htons((u_short)len + sizeof(struct udphdr)); /* @@ -772,12 +781,6 @@ udp_output(inp, m, addr, control, td) error = ip_output(m, inp->inp_options, &inp->inp_route, (inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST)), inp->inp_moptions, inp); - - if (addr) { - in_pcbdisconnect(inp); - inp->inp_laddr = laddr; /* XXX rehash? */ - splx(s); - } return (error); release: |