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
This commit is contained in:
+26
-23
@@ -688,9 +688,10 @@ udp_output(inp, m, addr, control, td)
|
|||||||
{
|
{
|
||||||
register struct udpiphdr *ui;
|
register struct udpiphdr *ui;
|
||||||
register int len = m->m_pkthdr.len;
|
register int len = m->m_pkthdr.len;
|
||||||
struct in_addr laddr;
|
struct in_addr faddr, laddr;
|
||||||
struct sockaddr_in *sin;
|
struct sockaddr_in *sin;
|
||||||
int s = 0, error = 0;
|
int error = 0;
|
||||||
|
u_short fport, lport;
|
||||||
|
|
||||||
#ifdef MAC
|
#ifdef MAC
|
||||||
mac_create_mbuf_from_socket(inp->inp_socket, m);
|
mac_create_mbuf_from_socket(inp->inp_socket, m);
|
||||||
@@ -704,26 +705,36 @@ udp_output(inp, m, addr, control, td)
|
|||||||
goto release;
|
goto release;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
laddr = inp->inp_laddr;
|
||||||
|
lport = inp->inp_lport;
|
||||||
if (addr) {
|
if (addr) {
|
||||||
sin = (struct sockaddr_in *)addr;
|
sin = (struct sockaddr_in *)addr;
|
||||||
if (td && jailed(td->td_ucred))
|
if (td && jailed(td->td_ucred))
|
||||||
prison_remote_ip(td->td_ucred, 0, &sin->sin_addr.s_addr);
|
prison_remote_ip(td->td_ucred, 0, &sin->sin_addr.s_addr);
|
||||||
laddr = inp->inp_laddr;
|
|
||||||
if (inp->inp_faddr.s_addr != INADDR_ANY) {
|
if (inp->inp_faddr.s_addr != INADDR_ANY) {
|
||||||
error = EISCONN;
|
error = EISCONN;
|
||||||
goto release;
|
goto release;
|
||||||
}
|
}
|
||||||
/*
|
error = in_pcbconnect_setup(inp, addr, &laddr.s_addr, &lport,
|
||||||
* Must block input while temporarily connected.
|
&faddr.s_addr, &fport, NULL, td);
|
||||||
*/
|
if (error)
|
||||||
s = splnet();
|
|
||||||
error = in_pcbconnect(inp, addr, td);
|
|
||||||
if (error) {
|
|
||||||
splx(s);
|
|
||||||
goto release;
|
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 {
|
} 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;
|
error = ENOTCONN;
|
||||||
goto release;
|
goto release;
|
||||||
}
|
}
|
||||||
@@ -735,8 +746,6 @@ udp_output(inp, m, addr, control, td)
|
|||||||
M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
|
M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
|
||||||
if (m == 0) {
|
if (m == 0) {
|
||||||
error = ENOBUFS;
|
error = ENOBUFS;
|
||||||
if (addr)
|
|
||||||
splx(s);
|
|
||||||
goto release;
|
goto release;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -747,10 +756,10 @@ udp_output(inp, m, addr, control, td)
|
|||||||
ui = mtod(m, struct udpiphdr *);
|
ui = mtod(m, struct udpiphdr *);
|
||||||
bzero(ui->ui_x1, sizeof(ui->ui_x1)); /* XXX still needed? */
|
bzero(ui->ui_x1, sizeof(ui->ui_x1)); /* XXX still needed? */
|
||||||
ui->ui_pr = IPPROTO_UDP;
|
ui->ui_pr = IPPROTO_UDP;
|
||||||
ui->ui_src = inp->inp_laddr;
|
ui->ui_src = laddr;
|
||||||
ui->ui_dst = inp->inp_faddr;
|
ui->ui_dst = faddr;
|
||||||
ui->ui_sport = inp->inp_lport;
|
ui->ui_sport = lport;
|
||||||
ui->ui_dport = inp->inp_fport;
|
ui->ui_dport = fport;
|
||||||
ui->ui_ulen = htons((u_short)len + sizeof(struct udphdr));
|
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,
|
error = ip_output(m, inp->inp_options, &inp->inp_route,
|
||||||
(inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST)),
|
(inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST)),
|
||||||
inp->inp_moptions, inp);
|
inp->inp_moptions, inp);
|
||||||
|
|
||||||
if (addr) {
|
|
||||||
in_pcbdisconnect(inp);
|
|
||||||
inp->inp_laddr = laddr; /* XXX rehash? */
|
|
||||||
splx(s);
|
|
||||||
}
|
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
release:
|
release:
|
||||||
|
|||||||
Reference in New Issue
Block a user