Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/ip_output.c
Show First 20 Lines • Show All 102 Lines • ▼ Show 20 Lines | |||||
extern int in_mcast_loop; | extern int in_mcast_loop; | ||||
extern struct protosw inetsw[]; | extern struct protosw inetsw[]; | ||||
static inline int | static inline int | ||||
ip_output_pfil(struct mbuf **mp, struct ifnet *ifp, struct inpcb *inp, | ip_output_pfil(struct mbuf **mp, struct ifnet *ifp, struct inpcb *inp, | ||||
struct sockaddr_in *dst, int *fibnum, int *error) | struct sockaddr_in *dst, int *fibnum, int *error) | ||||
{ | { | ||||
struct m_tag *fwd_tag = NULL; | |||||
struct mbuf *m; | struct mbuf *m; | ||||
struct in_addr odst; | struct in_addr odst; | ||||
struct ip *ip; | struct ip *ip; | ||||
m = *mp; | m = *mp; | ||||
ip = mtod(m, struct ip *); | ip = mtod(m, struct ip *); | ||||
/* Run through list of hooks for output packets. */ | /* Run through list of hooks for output packets. */ | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | |||||
#endif | #endif | ||||
m->m_pkthdr.csum_flags |= | m->m_pkthdr.csum_flags |= | ||||
CSUM_IP_CHECKED | CSUM_IP_VALID; | CSUM_IP_CHECKED | CSUM_IP_VALID; | ||||
*error = netisr_queue(NETISR_IP, m); | *error = netisr_queue(NETISR_IP, m); | ||||
return 1; /* Finished */ | return 1; /* Finished */ | ||||
} | } | ||||
/* Or forward to some other address? */ | /* Or forward to some other address? */ | ||||
if ((m->m_flags & M_IP_NEXTHOP) && | if (IP_HAS_NEXTHOP(m) && !ip_get_fwdtag(m, dst, NULL)) { | ||||
((fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL)) != NULL)) { | |||||
bcopy((fwd_tag+1), dst, sizeof(struct sockaddr_in)); | |||||
m->m_flags |= M_SKIP_FIREWALL; | m->m_flags |= M_SKIP_FIREWALL; | ||||
m->m_flags &= ~M_IP_NEXTHOP; | ip_flush_fwdtag(m); | ||||
m_tag_delete(m, fwd_tag); | |||||
return -1; /* Reloop for CHANGE of dst */ | return -1; /* Reloop for CHANGE of dst */ | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
/* | /* | ||||
* IP output. The packet in mbuf chain m contains a skeletal IP | * IP output. The packet in mbuf chain m contains a skeletal IP | ||||
▲ Show 20 Lines • Show All 1,208 Lines • ▼ Show 20 Lines | if (copym != NULL) { | ||||
/* | /* | ||||
* We don't bother to fragment if the IP length is greater | * We don't bother to fragment if the IP length is greater | ||||
* than the interface's MTU. Can this possibly matter? | * than the interface's MTU. Can this possibly matter? | ||||
*/ | */ | ||||
ip = mtod(copym, struct ip *); | ip = mtod(copym, struct ip *); | ||||
ip->ip_sum = 0; | ip->ip_sum = 0; | ||||
ip->ip_sum = in_cksum(copym, hlen); | ip->ip_sum = in_cksum(copym, hlen); | ||||
if_simloop(ifp, copym, AF_INET, 0); | if_simloop(ifp, copym, AF_INET, 0); | ||||
} | |||||
} | |||||
int | |||||
ip_set_fwdtag(struct mbuf *m, struct sockaddr_in *dst, u_short ifidx) | |||||
{ | |||||
struct sockaddr_in *sa; | |||||
struct m_tag *fwd_tag; | |||||
(void)ifidx; /* XXX: store after dst, or make struct? */ | |||||
fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL); | |||||
if (fwd_tag != NULL) { | |||||
KASSERT(((struct sockaddr *)(fwd_tag+1))->sa_family == | |||||
AF_INET, ("%s: !AF_INET", __func__)); | |||||
m_tag_unlink(m, fwd_tag); | |||||
} else { | |||||
fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD, sizeof(*dst), | |||||
M_NOWAIT); | |||||
if (fwd_tag == NULL) { | |||||
return 1; | |||||
ae: I think return error code is better than magic value. How about (ENOBUFS)? | |||||
} | |||||
} | |||||
sa = (struct sockaddr_in *)(fwd_tag+1); | |||||
aeUnsubmitted Done Inline ActionsI think it would be good add KASSERT(dst->sin_family == AF_INET) for consistency. ae: I think it would be good add KASSERT(dst->sin_family == AF_INET) for consistency. | |||||
bcopy(dst, sa, sizeof(*dst)); | |||||
m->m_flags |= M_IP_NEXTHOP; | |||||
if (in_localip(sa->sin_addr)) | |||||
m->m_flags |= M_FASTFWD_OURS; | |||||
else | |||||
m->m_flags &= ~M_FASTFWD_OURS; | |||||
m_tag_prepend(m, fwd_tag); | |||||
return 0; | |||||
aeUnsubmitted Done Inline Actions"Values in return statements should be enclosed in parentheses." (c) style(9) :-) ae: "Values in return statements should be enclosed in parentheses." (c) style(9) :-) | |||||
} | |||||
int | |||||
ip_get_fwdtag(struct mbuf *m, struct sockaddr_in *dst, u_short *ifidx) | |||||
{ | |||||
struct m_tag *fwd_tag; | |||||
fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL); | |||||
if (fwd_tag == NULL) { | |||||
return 1; | |||||
aeUnsubmitted Done Inline ActionsENOENT/ESRCH ae: ENOENT/ESRCH | |||||
} | |||||
KASSERT(((struct sockaddr *)(fwd_tag+1))->sa_family == AF_INET, | |||||
("%s: !AF_INET", __func__)); | |||||
if (dst != NULL) { | |||||
bcopy((fwd_tag+1), dst, sizeof(*dst)); | |||||
} | |||||
if (ifidx != NULL) { | |||||
/* XXX ifidx is not yet defined */ | |||||
} | |||||
return 0; | |||||
} | |||||
void | |||||
ip_flush_fwdtag(struct mbuf *m) | |||||
{ | |||||
struct m_tag *fwd_tag; | |||||
fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL); | |||||
if (fwd_tag != NULL) { | |||||
KASSERT(((struct sockaddr *)(fwd_tag+1))->sa_family == | |||||
AF_INET, ("%s: !AF_INET", __func__)); | |||||
m->m_flags &= ~(M_IP_NEXTHOP | M_FASTFWD_OURS); | |||||
m_tag_delete(m, fwd_tag); | |||||
} | } | ||||
} | } |
I think return error code is better than magic value. How about (ENOBUFS)?