Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/raw_ip.c
Show First 20 Lines • Show All 400 Lines • ▼ Show 20 Lines | if (appended == 0 && | ||||
m_freem(m); | m_freem(m); | ||||
return (IPPROTO_DONE); | return (IPPROTO_DONE); | ||||
} | } | ||||
/* | /* | ||||
* Generate IP header and pass packet to ip_output. Tack on options user may | * Generate IP header and pass packet to ip_output. Tack on options user may | ||||
* have setup with control call. | * have setup with control call. | ||||
*/ | */ | ||||
int | static int | ||||
rip_output(struct mbuf *m, struct socket *so, ...) | rip_send(struct socket *so, int pruflags, struct mbuf *m, struct sockaddr *nam, | ||||
struct mbuf *control, struct thread *td) | |||||
{ | { | ||||
struct epoch_tracker et; | struct epoch_tracker et; | ||||
struct ip *ip; | struct ip *ip; | ||||
int error; | struct inpcb *inp; | ||||
struct inpcb *inp = sotoinpcb(so); | in_addr_t *dst; | ||||
va_list ap; | int error, flags, cnt, hlen; | ||||
u_long dst; | |||||
int flags = ((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0) | | |||||
IP_ALLOWBROADCAST; | |||||
int cnt, hlen; | |||||
u_char opttype, optlen, *cp; | u_char opttype, optlen, *cp; | ||||
va_start(ap, so); | inp = sotoinpcb(so); | ||||
dst = va_arg(ap, u_long); | KASSERT(inp != NULL, ("rip_send: inp == NULL")); | ||||
va_end(ap); | |||||
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; | |||||
melifaro: Q: why do we store reference instead of just saving the value? | |||||
Done Inline ActionsAt this point inp isn't locked. On the copyout it will be locked. Well, inp_faddr can not change, I believe. But reading value out in the locked section, kinda more cool. glebius: At this point inp isn't locked. On the copyout it will be locked. Well, inp_faddr can not… | |||||
} 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, | * If the user handed us a complete IP packet, use it. Otherwise, | ||||
* allocate an mbuf for a header and fill it in. | * allocate an mbuf for a header and fill it in. | ||||
*/ | */ | ||||
if ((inp->inp_flags & INP_HDRINCL) == 0) { | if ((inp->inp_flags & INP_HDRINCL) == 0) { | ||||
if (m->m_pkthdr.len + sizeof(struct ip) > IP_MAXPACKET) { | if (m->m_pkthdr.len + sizeof(struct ip) > IP_MAXPACKET) { | ||||
m_freem(m); | m_freem(m); | ||||
return(EMSGSIZE); | return(EMSGSIZE); | ||||
} | } | ||||
M_PREPEND(m, sizeof(struct ip), M_NOWAIT); | M_PREPEND(m, sizeof(struct ip), M_NOWAIT); | ||||
if (m == NULL) | if (m == NULL) | ||||
return(ENOBUFS); | return(ENOBUFS); | ||||
INP_RLOCK(inp); | INP_RLOCK(inp); | ||||
ip = mtod(m, struct ip *); | ip = mtod(m, struct ip *); | ||||
ip->ip_tos = inp->inp_ip_tos; | ip->ip_tos = inp->inp_ip_tos; | ||||
if (inp->inp_flags & INP_DONTFRAG) | if (inp->inp_flags & INP_DONTFRAG) | ||||
ip->ip_off = htons(IP_DF); | ip->ip_off = htons(IP_DF); | ||||
else | else | ||||
ip->ip_off = htons(0); | ip->ip_off = htons(0); | ||||
ip->ip_p = inp->inp_ip_p; | ip->ip_p = inp->inp_ip_p; | ||||
ip->ip_len = htons(m->m_pkthdr.len); | ip->ip_len = htons(m->m_pkthdr.len); | ||||
ip->ip_src = inp->inp_laddr; | ip->ip_src = inp->inp_laddr; | ||||
ip->ip_dst.s_addr = dst; | ip->ip_dst.s_addr = *dst; | ||||
#ifdef ROUTE_MPATH | #ifdef ROUTE_MPATH | ||||
if (CALC_FLOWID_OUTBOUND) { | if (CALC_FLOWID_OUTBOUND) { | ||||
uint32_t hash_type, hash_val; | uint32_t hash_type, hash_val; | ||||
hash_val = fib4_calc_software_hash(ip->ip_src, | hash_val = fib4_calc_software_hash(ip->ip_src, | ||||
ip->ip_dst, 0, 0, ip->ip_p, &hash_type); | ip->ip_dst, 0, 0, ip->ip_p, &hash_type); | ||||
m->m_pkthdr.flowid = hash_val; | m->m_pkthdr.flowid = hash_val; | ||||
M_HASHTYPE_SET(m, hash_type); | M_HASHTYPE_SET(m, hash_type); | ||||
▲ Show 20 Lines • Show All 506 Lines • ▼ Show 20 Lines | rip_shutdown(struct socket *so) | ||||
inp = sotoinpcb(so); | inp = sotoinpcb(so); | ||||
KASSERT(inp != NULL, ("rip_shutdown: inp == NULL")); | KASSERT(inp != NULL, ("rip_shutdown: inp == NULL")); | ||||
INP_WLOCK(inp); | INP_WLOCK(inp); | ||||
socantsendmore(so); | socantsendmore(so); | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
return (0); | 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 */ | #endif /* INET */ | ||||
static int | static int | ||||
rip_pcblist(SYSCTL_HANDLER_ARGS) | rip_pcblist(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
struct inpcb_iterator inpi = INP_ALL_ITERATOR(&V_ripcbinfo, | struct inpcb_iterator inpi = INP_ALL_ITERATOR(&V_ripcbinfo, | ||||
INPLOOKUP_RLOCKPCB); | INPLOOKUP_RLOCKPCB); | ||||
▲ Show 20 Lines • Show All 80 Lines • Show Last 20 Lines |
Q: why do we store reference instead of just saving the value?