Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/ip_fastfwd.c
Show First 20 Lines • Show All 105 Lines • ▼ Show 20 Lines | |||||
#include <netinet/in_var.h> | #include <netinet/in_var.h> | ||||
#include <netinet/ip.h> | #include <netinet/ip.h> | ||||
#include <netinet/ip_var.h> | #include <netinet/ip_var.h> | ||||
#include <netinet/ip_icmp.h> | #include <netinet/ip_icmp.h> | ||||
#include <netinet/ip_options.h> | #include <netinet/ip_options.h> | ||||
#include <machine/in_cksum.h> | #include <machine/in_cksum.h> | ||||
#define V_ipsendredirects VNET(ipsendredirects) | |||||
ae: It is already defined in ip_var.h. | |||||
Done Inline ActionsIt is declared in ip_var.h but we need to access it here so we have this #define. gnn: It is declared in ip_var.h but we need to access it here so we have this #define. | |||||
Not Done Inline ActionsI meant it is already defined in ip_var.h and ip_var.h is included in this file. ae: I meant it is already defined in ip_var.h and ip_var.h is included in this file. | |||||
static struct mbuf * | |||||
ip_redir_alloc(struct mbuf *m, struct nhop_object *nh, | |||||
struct ip *ip, in_addr_t *addr) | |||||
{ | |||||
struct mbuf *mcopy = m_gethdr(M_NOWAIT, m->m_type); | |||||
if (mcopy != NULL && !m_dup_pkthdr(mcopy, m, M_NOWAIT)) { | |||||
aeUnsubmitted Not Done Inline ActionsWe still going to the panic in case when m_gethdr() returns NULL. if (mcopy == NULL || m_dup_pkthdr() == 0) ae: We still going to the panic in case when m_gethdr() returns NULL.
This condition shoud be
```… | |||||
/* | |||||
* It's probably ok if the pkthdr dup fails (because | |||||
* the deep copy of the tag chain failed), but for now | |||||
* be conservative and just discard the copy since | |||||
* code below may some day want the tags. | |||||
*/ | |||||
m_free(mcopy); | |||||
return (NULL); | |||||
} | |||||
mcopy->m_len = min(ntohs(ip->ip_len), M_TRAILINGSPACE(mcopy)); | |||||
mcopy->m_pkthdr.len = mcopy->m_len; | |||||
m_copydata(m, 0, mcopy->m_len, mtod(mcopy, caddr_t)); | |||||
if (nh != NULL && | |||||
melifaroUnsubmitted Not Done Inline ActionsNit: nh is always != NULL, as we return if ip_findroute() returns error. melifaro: Nit: nh is always != NULL, as we return if `ip_findroute()` returns error. | |||||
((nh->nh_flags & (NHF_REDIRECT|NHF_DEFAULT)) == 0)) { | |||||
struct in_ifaddr *nh_ia = (struct in_ifaddr *)(nh->nh_ifa); | |||||
u_long src = ntohl(ip->ip_src.s_addr); | |||||
if (nh_ia != NULL && (src & nh_ia->ia_subnetmask) == nh_ia->ia_subnet) { | |||||
if (nh->nh_flags & NHF_GATEWAY) | |||||
*addr = nh->gw4_sa.sin_addr.s_addr; | |||||
else | |||||
*addr = ip->ip_dst.s_addr; | |||||
} | |||||
} | |||||
return (mcopy); | |||||
} | |||||
static int | static int | ||||
ip_findroute(struct nhop_object **pnh, struct in_addr dest, struct mbuf *m) | ip_findroute(struct nhop_object **pnh, struct in_addr dest, struct mbuf *m) | ||||
{ | { | ||||
struct nhop_object *nh; | struct nhop_object *nh; | ||||
nh = fib4_lookup(M_GETFIB(m), dest, 0, NHR_NONE, | nh = fib4_lookup(M_GETFIB(m), dest, 0, NHR_NONE, | ||||
m->m_pkthdr.flowid); | m->m_pkthdr.flowid); | ||||
if (nh == NULL) { | if (nh == NULL) { | ||||
Show All 29 Lines | |||||
* otherwise mbuf is returned and the packet should be delivered | * otherwise mbuf is returned and the packet should be delivered | ||||
* to ip_input for full processing. | * to ip_input for full processing. | ||||
*/ | */ | ||||
struct mbuf * | struct mbuf * | ||||
ip_tryforward(struct mbuf *m) | ip_tryforward(struct mbuf *m) | ||||
{ | { | ||||
struct ip *ip; | struct ip *ip; | ||||
struct mbuf *m0 = NULL; | struct mbuf *m0 = NULL; | ||||
struct nhop_object *nh; | struct nhop_object *nh = NULL; | ||||
struct sockaddr_in dst; | struct sockaddr_in dst; | ||||
struct in_addr dest, odest, rtdest; | struct in_addr dest, odest, rtdest; | ||||
uint16_t ip_len, ip_off; | uint16_t ip_len, ip_off; | ||||
int error = 0; | int error = 0; | ||||
struct m_tag *fwd_tag = NULL; | struct m_tag *fwd_tag = NULL; | ||||
struct mbuf *mcopy = NULL; | |||||
struct in_addr redest; | |||||
/* | /* | ||||
* Are we active and forwarding packets? | * Are we active and forwarding packets? | ||||
*/ | */ | ||||
M_ASSERTVALID(m); | M_ASSERTVALID(m); | ||||
M_ASSERTPKTHDR(m); | M_ASSERTPKTHDR(m); | ||||
#ifdef ALTQ | #ifdef ALTQ | ||||
▲ Show 20 Lines • Show All 208 Lines • ▼ Show 20 Lines | passout: | ||||
dst.sin_family = AF_INET; | dst.sin_family = AF_INET; | ||||
dst.sin_len = sizeof(dst); | dst.sin_len = sizeof(dst); | ||||
if (nh->nh_flags & NHF_GATEWAY) | if (nh->nh_flags & NHF_GATEWAY) | ||||
dst.sin_addr = nh->gw4_sa.sin_addr; | dst.sin_addr = nh->gw4_sa.sin_addr; | ||||
else | else | ||||
dst.sin_addr = dest; | dst.sin_addr = dest; | ||||
/* | /* | ||||
* Handle redirect case. | |||||
*/ | |||||
redest.s_addr = 0; | |||||
if (V_ipsendredirects && (nh->nh_ifp == m->m_pkthdr.rcvif)) | |||||
mcopy = ip_redir_alloc(m, nh, ip, &redest.s_addr); | |||||
Not Done Inline ActionsWould it be possible to move all of the code under condition here in a separate function? melifaro: Would it be possible to move all of the code under condition here in a separate function? | |||||
Done Inline ActionsI'd prefer to do that both here and in ip_input, in a followup, cleanup change. gnn: I'd prefer to do that both here and in ip_input, in a followup, cleanup change. | |||||
Done Inline ActionsGiven the change is mostly about adding this piece of code, it would be beneficial to start with "cleaned up" version :-) melifaro: Given the change is mostly about adding this piece of code, it would be beneficial to start… | |||||
/* | |||||
* Check if packet fits MTU or if hardware will fragment for us | * Check if packet fits MTU or if hardware will fragment for us | ||||
*/ | */ | ||||
if (ip_len <= nh->nh_mtu) { | if (ip_len <= nh->nh_mtu) { | ||||
/* | /* | ||||
* Avoid confusing lower layers. | * Avoid confusing lower layers. | ||||
*/ | */ | ||||
m_clrprotoflags(m); | m_clrprotoflags(m); | ||||
/* | /* | ||||
* Send off the packet via outgoing interface | * Send off the packet via outgoing interface | ||||
*/ | */ | ||||
Done Inline ActionsNULL pointer dereference is possible here in case, when m_gethdr() returns NULL. ae: NULL pointer dereference is possible here in case, when m_gethdr() returns NULL. | |||||
IP_PROBE(send, NULL, NULL, ip, nh->nh_ifp, ip, NULL); | IP_PROBE(send, NULL, NULL, ip, nh->nh_ifp, ip, NULL); | ||||
error = (*nh->nh_ifp->if_output)(nh->nh_ifp, m, | error = (*nh->nh_ifp->if_output)(nh->nh_ifp, m, | ||||
(struct sockaddr *)&dst, NULL); | (struct sockaddr *)&dst, NULL); | ||||
} else { | } else { | ||||
Done Inline ActionsIt seem nh here can not be NULL. ae: It seem nh here can not be NULL. | |||||
/* | /* | ||||
* Handle EMSGSIZE with icmp reply needfrag for TCP MTU discovery | * Handle EMSGSIZE with icmp reply needfrag for TCP MTU discovery | ||||
*/ | */ | ||||
if (ip_off & IP_DF) { | if (ip_off & IP_DF) { | ||||
IPSTAT_INC(ips_cantfrag); | IPSTAT_INC(ips_cantfrag); | ||||
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, | icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, | ||||
0, nh->nh_mtu); | 0, nh->nh_mtu); | ||||
goto consumed; | goto consumed; | ||||
Show All 38 Lines | passout: | ||||
} | } | ||||
if (error != 0) | if (error != 0) | ||||
IPSTAT_INC(ips_odropped); | IPSTAT_INC(ips_odropped); | ||||
else { | else { | ||||
IPSTAT_INC(ips_forward); | IPSTAT_INC(ips_forward); | ||||
IPSTAT_INC(ips_fastforward); | IPSTAT_INC(ips_fastforward); | ||||
} | } | ||||
/* Send required redirect */ | |||||
if (mcopy != NULL) { | |||||
icmp_error(mcopy, ICMP_REDIRECT, ICMP_REDIRECT_HOST, redest.s_addr, 0); | |||||
mcopy = NULL; /* Freed by caller */ | |||||
} | |||||
consumed: | consumed: | ||||
if (mcopy != NULL) | |||||
m_freem(mcopy); | |||||
return NULL; | return NULL; | ||||
drop: | drop: | ||||
if (m) | if (m) | ||||
m_freem(m); | m_freem(m); | ||||
return NULL; | return NULL; | ||||
} | } |
It is already defined in ip_var.h.