mirror of
https://github.com/opnsense/src.git
synced 2026-06-11 09:41:03 -04:00
raw ip: merge rip_output() into rip_send()
While here, address the unlocked 'dst' read. Solve that by storing a pointer either to the inpcb or to the sockaddr. If we end up copying address out of the inpcb, that would be done under the read lock section. Reviewed by: melifaro Differential revision: https://reviews.freebsd.org/D36127
This commit is contained in:
parent
8c77967ecc
commit
3d2041c035
2 changed files with 40 additions and 58 deletions
|
|
@ -236,7 +236,6 @@ void ip_fillid(struct ip *);
|
|||
int rip_ctloutput(struct socket *, struct sockopt *);
|
||||
void rip_ctlinput(int, struct sockaddr *, void *);
|
||||
int rip_input(struct mbuf **, int *, int);
|
||||
int rip_output(struct mbuf *, struct socket *, ...);
|
||||
int ipip_input(struct mbuf **, int *, int);
|
||||
int rsvp_input(struct mbuf **, int *, int);
|
||||
int ip_rsvp_init(struct socket *);
|
||||
|
|
|
|||
|
|
@ -406,23 +406,50 @@ rip_input(struct mbuf **mp, int *offp, int proto)
|
|||
* Generate IP header and pass packet to ip_output. Tack on options user may
|
||||
* have setup with control call.
|
||||
*/
|
||||
int
|
||||
rip_output(struct mbuf *m, struct socket *so, ...)
|
||||
static int
|
||||
rip_send(struct socket *so, int pruflags, struct mbuf *m, struct sockaddr *nam,
|
||||
struct mbuf *control, struct thread *td)
|
||||
{
|
||||
struct epoch_tracker et;
|
||||
struct ip *ip;
|
||||
int error;
|
||||
struct inpcb *inp = sotoinpcb(so);
|
||||
va_list ap;
|
||||
u_long dst;
|
||||
int flags = ((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0) |
|
||||
IP_ALLOWBROADCAST;
|
||||
int cnt, hlen;
|
||||
struct inpcb *inp;
|
||||
in_addr_t *dst;
|
||||
int error, flags, cnt, hlen;
|
||||
u_char opttype, optlen, *cp;
|
||||
|
||||
va_start(ap, so);
|
||||
dst = va_arg(ap, u_long);
|
||||
va_end(ap);
|
||||
inp = sotoinpcb(so);
|
||||
KASSERT(inp != NULL, ("rip_send: inp == NULL"));
|
||||
|
||||
if (control != NULL) {
|
||||
m_freem(control);
|
||||
control = NULL;
|
||||
}
|
||||
|
||||
if (so->so_state & SS_ISCONNECTED) {
|
||||
if (nam) {
|
||||
error = EISCONN;
|
||||
m_freem(m);
|
||||
return (error);
|
||||
}
|
||||
dst = &inp->inp_faddr.s_addr;
|
||||
} else {
|
||||
if (nam == NULL)
|
||||
error = ENOTCONN;
|
||||
else if (nam->sa_family != AF_INET)
|
||||
error = EAFNOSUPPORT;
|
||||
else if (nam->sa_len != sizeof(struct sockaddr_in))
|
||||
error = EINVAL;
|
||||
else
|
||||
error = 0;
|
||||
if (error != 0) {
|
||||
m_freem(m);
|
||||
return (error);
|
||||
}
|
||||
dst = &((struct sockaddr_in *)nam)->sin_addr.s_addr;
|
||||
}
|
||||
|
||||
flags = ((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0) |
|
||||
IP_ALLOWBROADCAST;
|
||||
|
||||
/*
|
||||
* If the user handed us a complete IP packet, use it. Otherwise,
|
||||
|
|
@ -447,7 +474,7 @@ rip_output(struct mbuf *m, struct socket *so, ...)
|
|||
ip->ip_p = inp->inp_ip_p;
|
||||
ip->ip_len = htons(m->m_pkthdr.len);
|
||||
ip->ip_src = inp->inp_laddr;
|
||||
ip->ip_dst.s_addr = dst;
|
||||
ip->ip_dst.s_addr = *dst;
|
||||
#ifdef ROUTE_MPATH
|
||||
if (CALC_FLOWID_OUTBOUND) {
|
||||
uint32_t hash_type, hash_val;
|
||||
|
|
@ -971,50 +998,6 @@ rip_shutdown(struct socket *so)
|
|||
INP_WUNLOCK(inp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
rip_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
|
||||
struct mbuf *control, struct thread *td)
|
||||
{
|
||||
struct inpcb *inp;
|
||||
u_long dst;
|
||||
int error;
|
||||
|
||||
inp = sotoinpcb(so);
|
||||
KASSERT(inp != NULL, ("rip_send: inp == NULL"));
|
||||
|
||||
if (control != NULL) {
|
||||
m_freem(control);
|
||||
control = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: 'dst' reads below are unlocked.
|
||||
*/
|
||||
if (so->so_state & SS_ISCONNECTED) {
|
||||
if (nam) {
|
||||
error = EISCONN;
|
||||
goto release;
|
||||
}
|
||||
dst = inp->inp_faddr.s_addr; /* Unlocked read. */
|
||||
} else {
|
||||
error = 0;
|
||||
if (nam == NULL)
|
||||
error = ENOTCONN;
|
||||
else if (nam->sa_family != AF_INET)
|
||||
error = EAFNOSUPPORT;
|
||||
else if (nam->sa_len != sizeof(struct sockaddr_in))
|
||||
error = EINVAL;
|
||||
if (error != 0)
|
||||
goto release;
|
||||
dst = ((struct sockaddr_in *)nam)->sin_addr.s_addr;
|
||||
}
|
||||
return (rip_output(m, so, dst));
|
||||
|
||||
release:
|
||||
m_freem(m);
|
||||
return (error);
|
||||
}
|
||||
#endif /* INET */
|
||||
|
||||
static int
|
||||
|
|
|
|||
Loading…
Reference in a new issue