本文整理汇总了C++中icmp_send函数的典型用法代码示例。如果您正苦于以下问题:C++ icmp_send函数的具体用法?C++ icmp_send怎么用?C++ icmp_send使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了icmp_send函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: ip_expire
static void ip_expire(unsigned long arg)
{
struct ipq *qp;
qp = (struct ipq *)arg;
/*
* Send an ICMP "Fragment Reassembly Timeout" message.
*/
ip_statistics.IpReasmTimeout++;
ip_statistics.IpReasmFails++;
/* This if is always true... shrug */
if(qp->fragments!=NULL)
icmp_send(qp->fragments->skb,ICMP_TIME_EXCEEDED,
ICMP_EXC_FRAGTIME, 0, qp->dev);
/*
* Nuke the fragment queue.
*/
ip_free(qp);
}
示例2: ip4ip6_tnl_xmit
static inline int
ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct ip6_tnl *t = netdev_priv(dev);
struct iphdr *iph = ip_hdr(skb);
int encap_limit = -1;
struct flowi fl;
__u8 dsfield;
__u32 mtu;
int err;
if ((t->parms.proto != IPPROTO_IPIP && t->parms.proto != 0) ||
!ip6_tnl_xmit_ctl(t))
return -1;
if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
encap_limit = t->parms.encap_limit;
memcpy(&fl, &t->fl, sizeof (fl));
fl.proto = IPPROTO_IPIP;
dsfield = ipv4_get_dsfield(iph);
if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS))
fl.fl6_flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT)
& IPV6_TCLASS_MASK;
err = ip6_tnl_xmit2(skb, dev, dsfield, &fl, encap_limit, &mtu);
if (err != 0) {
/* XXX: send ICMP error even if DF is not set. */
if (err == -EMSGSIZE)
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
htonl(mtu));
return -1;
}
return 0;
}
示例3: ipv6_validate_packet_len
static bool ipv6_validate_packet_len(struct sk_buff *skb_in, struct sk_buff *skb_out)
{
struct ipv6hdr *ip6_hdr = ipv6_hdr(skb_out);
struct hdr_iterator iterator = HDR_ITERATOR_INIT(ip6_hdr);
unsigned int ipv6_mtu;
unsigned int ipv4_mtu;
if (skb_out->len <= skb_out->dev->mtu)
return true;
hdr_iterator_last(&iterator);
if (iterator.hdr_type == IPPROTO_ICMPV6) {
struct icmp6hdr *icmpv6_hdr = icmp6_hdr(skb_out);
if (is_icmp6_error(icmpv6_hdr->icmp6_type)) {
int new_packet_len = skb_out->dev->mtu;
int l3_payload_len = new_packet_len - (iterator.data - (void *) ip6_hdr);
skb_trim(skb_out, new_packet_len);
ip6_hdr->payload_len = cpu_to_be16(l3_payload_len);
icmpv6_hdr->icmp6_cksum = 0;
icmpv6_hdr->icmp6_cksum = csum_ipv6_magic(&ip6_hdr->saddr, &ip6_hdr->daddr,
l3_payload_len, IPPROTO_ICMPV6, csum_partial(icmpv6_hdr, l3_payload_len, 0));
return true;
}
}
ipv6_mtu = skb_out->dev->mtu;
ipv4_mtu = skb_in->dev->mtu;
log_debug("Packet is too large for the outgoing MTU and IPv6 routers don't do fragmentation. "
"Dropping...");
icmp_send(skb_in, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
cpu_to_be32(min_uint(ipv6_mtu, ipv4_mtu + 20)));
return false;
}
示例4: command_ping
/**
* \ingroup tcpcmd
* \b PING-Befehl Sende "Ping" an angegebene Adresse
*/
int16_t command_ping (char *outbuffer)
{
uint32_t var = 0;
if (getLong(&var))
{
unsigned long dest_ip=0;
for (uint8_t i=0; i<4; ++i) {
dest_ip += (var<<(8*i));
if (!getLong(&var))
break;
}
//ARP Request senden
arp_request (dest_ip);
//ICMP-Nachricht Type=8 Code=0: Echo-Anfrage
//TODO: Sequenznummer, Identifier
icmp_send(dest_ip,0x08,0x00,1,1);
}
return 0;
}
示例5: icmp_hnd_echo_request
static int icmp_hnd_echo_request(const struct icmphdr *icmph,
const struct icmpbody_echo *echo_req,
struct sk_buff *skb) {
size_t len;
struct icmpbody_echo *echo_rep;
if (icmph->code != 0) {
skb_free(skb);
return 0; /* error: bad code */
}
len = ip_data_length(ip_hdr(skb));
if (sizeof *icmph + sizeof *echo_req > len) {
skb_free(skb);
return 0; /* error: invalid length */
}
len -= sizeof *icmph + sizeof *echo_req;
echo_rep = &icmp_hdr(skb)->body[0].echo;
return icmp_send(ICMP_ECHO_REPLY, 0, echo_rep,
sizeof *echo_rep + len, skb);
}
示例6: ipip6_rcv
static int ipip6_rcv(struct sk_buff *skb)
{
struct iphdr *iph;
struct ip_tunnel *tunnel;
if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
goto out;
iph = skb->nh.iph;
read_lock(&ipip6_lock);
if ((tunnel = ipip6_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) {
secpath_reset(skb);
skb->mac.raw = skb->nh.raw;
skb->nh.raw = skb->data;
memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
IPCB(skb)->flags = 0;
skb->protocol = htons(ETH_P_IPV6);
skb->pkt_type = PACKET_HOST;
tunnel->stat.rx_packets++;
tunnel->stat.rx_bytes += skb->len;
skb->dev = tunnel->dev;
dst_release(skb->dst);
skb->dst = NULL;
nf_reset(skb);
ipip6_ecn_decapsulate(iph, skb);
netif_rx(skb);
read_unlock(&ipip6_lock);
return 0;
}
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0);
kfree_skb(skb);
read_unlock(&ipip6_lock);
out:
return 0;
}
示例7: gre_rcv
static int gre_rcv(struct sk_buff *skb)
{
struct tnl_ptk_info tpi;
bool csum_err = false;
#ifdef CONFIG_NET_IPGRE_BROADCAST
if (ipv4_is_multicast(ip_hdr(skb)->daddr)) {
/* Looped back packet, drop it! */
if (rt_is_output_route(skb_rtable(skb)))
goto drop;
}
#endif
if (parse_gre_header(skb, &tpi, &csum_err) < 0)
goto drop;
if (ipgre_rcv(skb, &tpi) == PACKET_RCVD)
return 0;
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
drop:
kfree_skb(skb);
return 0;
}
示例8: xfrm4_rcv_encap
int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
int encap_type)
{
int ret;
struct xfrm4_protocol *handler;
struct xfrm4_protocol __rcu **head = proto_handlers(nexthdr);
XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL;
XFRM_SPI_SKB_CB(skb)->family = AF_INET;
XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
if (!head)
goto out;
for_each_protocol_rcu(*head, handler)
if ((ret = handler->input_handler(skb, nexthdr, spi, encap_type)) != -EINVAL)
return ret;
out:
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
kfree_skb(skb);
return 0;
}
示例9: ip_vs_leave
/*
* Pass or drop the packet.
* Called by ip_vs_in, when the virtual service is available but
* no destination is available for a new connection.
*/
int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
struct ip_vs_protocol *pp)
{
__be16 _ports[2], *pptr;
struct iphdr *iph = ip_hdr(skb);
pptr = skb_header_pointer(skb, iph->ihl*4,
sizeof(_ports), _ports);
if (pptr == NULL) {
ip_vs_service_put(svc);
return NF_DROP;
}
/* if it is fwmark-based service, the cache_bypass sysctl is up
and the destination is RTN_UNICAST (and not local), then create
a cache_bypass connection entry */
if (sysctl_ip_vs_cache_bypass && svc->fwmark
&& (inet_addr_type(iph->daddr) == RTN_UNICAST)) {
int ret, cs;
struct ip_vs_conn *cp;
ip_vs_service_put(svc);
/* create a new connection entry */
IP_VS_DBG(6, "ip_vs_leave: create a cache_bypass entry\n");
cp = ip_vs_conn_new(iph->protocol,
iph->saddr, pptr[0],
iph->daddr, pptr[1],
0, 0,
IP_VS_CONN_F_BYPASS,
NULL);
if (cp == NULL)
return NF_DROP;
/* statistics */
ip_vs_in_stats(cp, skb);
/* set state */
cs = ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pp);
/* transmit the first SYN packet */
ret = cp->packet_xmit(skb, cp, pp);
/* do not touch skb anymore */
atomic_inc(&cp->in_pkts);
ip_vs_conn_put(cp);
return ret;
}
/*
* When the virtual ftp service is presented, packets destined
* for other services on the VIP may get here (except services
* listed in the ipvs table), pass the packets, because it is
* not ipvs job to decide to drop the packets.
*/
if ((svc->port == FTPPORT) && (pptr[1] != FTPPORT)) {
ip_vs_service_put(svc);
return NF_ACCEPT;
}
ip_vs_service_put(svc);
/*
* Notify the client that the destination is unreachable, and
* release the socket buffer.
* Since it is in IP layer, the TCP socket is not actually
* created, the TCP RST packet cannot be sent, instead that
* ICMP_PORT_UNREACH is sent here no matter it is TCP/UDP. --WZ
*/
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
return NF_DROP;
}
示例10: fw_in
static unsigned int
fw_in(unsigned int hooknum,
struct sk_buff **pskb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
int ret = FW_BLOCK;
u_int16_t redirpt;
/* Assume worse case: any hook could change packet */
(*pskb)->nfcache |= NFC_UNKNOWN | NFC_ALTERED;
if ((*pskb)->ip_summed == CHECKSUM_HW)
if (skb_checksum_help(*pskb, (out == NULL)))
return NF_DROP;
switch (hooknum) {
case NF_IP_PRE_ROUTING:
if (fwops->fw_acct_in)
fwops->fw_acct_in(fwops, PF_INET,
(struct net_device *)in,
&redirpt, pskb);
if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
*pskb = ip_ct_gather_frags(*pskb);
if (!*pskb)
return NF_STOLEN;
}
ret = fwops->fw_input(fwops, PF_INET, (struct net_device *)in,
&redirpt, pskb);
break;
case NF_IP_FORWARD:
/* Connection will only be set if it was
demasqueraded: if so, skip forward chain. */
if ((*pskb)->nfct)
ret = FW_ACCEPT;
else ret = fwops->fw_forward(fwops, PF_INET,
(struct net_device *)out,
&redirpt, pskb);
break;
case NF_IP_POST_ROUTING:
ret = fwops->fw_output(fwops, PF_INET,
(struct net_device *)out,
&redirpt, pskb);
if (ret == FW_ACCEPT || ret == FW_SKIP) {
if (fwops->fw_acct_out)
fwops->fw_acct_out(fwops, PF_INET,
(struct net_device *)out,
&redirpt,
pskb);
/* ip_conntrack_confirm return NF_DROP or NF_ACCEPT */
if (ip_conntrack_confirm(*pskb) == NF_DROP)
ret = FW_BLOCK;
}
break;
}
switch (ret) {
case FW_REJECT: {
/* Alexey says:
*
* Generally, routing is THE FIRST thing to make, when
* packet enters IP stack. Before packet is routed you
* cannot call any service routines from IP stack. */
struct iphdr *iph = (*pskb)->nh.iph;
if ((*pskb)->dst != NULL
|| ip_route_input(*pskb, iph->daddr, iph->saddr, iph->tos,
(struct net_device *)in) == 0)
icmp_send(*pskb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH,
0);
return NF_DROP;
}
case FW_ACCEPT:
case FW_SKIP:
if (hooknum == NF_IP_PRE_ROUTING) {
check_for_demasq(pskb);
check_for_redirect(*pskb);
} else if (hooknum == NF_IP_POST_ROUTING) {
check_for_unredirect(*pskb);
/* Handle ICMP errors from client here */
if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP
&& (*pskb)->nfct)
check_for_masq_error(pskb);
}
return NF_ACCEPT;
case FW_MASQUERADE:
if (hooknum == NF_IP_FORWARD) {
#ifdef CONFIG_IP_VS
/* check if it is for ip_vs */
if (check_for_ip_vs_out(pskb, okfn) == NF_STOLEN)
return NF_STOLEN;
#endif
//.........这里部分代码省略.........
示例11: icmp_error
int icmp_error(struct iphdr * __ip, int __type,
int __code, struct ifnet * __if)
{
// uint8_t icmp_buf[sizeof(struct icmp) + IP_MAXOPTLEN + 8];
struct icmp * icp;
int len;
/* TODO:
if (type != ICMP_REDIRECT)
icmpstat.icps_error++; */
/* Don't send error if not the first fragment
Ref.: TCP/IP Illustrated Volume 2, pg. 325 */
icp = (struct icmp *)__ip->opt;
if (__ip->ip_off & ~(IP_MF | IP_DF)) {
DCC_LOG1(LOG_WARNING, "not first fragment!; ip_off = %04x",
__ip->ip_off);
return -1;
}
len = MIN((__ip->hlen << 2) + 8 , ntohs(__ip->tot_len));
memcpy((void *)&(icp->icmp_ip), __ip, len);
/*
if ((ip->proto == IPPROTO_ICMP) && (type != ICMP_REDIRECT) &&
(totlen >= iplen + ICMP_MINLEN) ) {
TODO:
icmpstat.icps_oldicmp++;
return -1;
} */
/* Don't send error in response to a multicast or broadcast packet */
if (in_broadcast(__ip->daddr, __if) || IN_MULTICAST(__ip->daddr)) {
DCC_LOG(LOG_INFO, "broadcast/multicast!");
return -1;
}
if ((unsigned int)__type > ICMP_MAXTYPE) {
DCC_LOG(LOG_PANIC, "icmp_error");
return -1;
}
/* TODO:
icmpstat.icps_outhist[type]++; */
icp->icmp_type = __type;
icp->icmp_void = 0;
if (__type == ICMP_PARAMETERPROB) {
icp->icmp_pptr = __code;
__code = 0;
} else {
if ((__type == ICMP_DEST_UNREACH) &&
(__code == ICMP_FRAG_NEEDED) && (__if)) {
icp->icmp_nextmtu = htons(__if->if_mtu);
}
}
icp->icmp_code = __code;
return icmp_send(__ip, icp, len);
}
示例12: ip_expire
/*
* Oops, a fragment queue timed out. Kill it and send an ICMP reply.
*/
static void ip_expire(struct timer_list *t)
{
struct inet_frag_queue *frag = from_timer(frag, t, timer);
struct ipq *qp;
struct net *net;
qp = container_of(frag, struct ipq, q);
net = container_of(qp->q.net, struct net, ipv4.frags);
rcu_read_lock();
spin_lock(&qp->q.lock);
if (qp->q.flags & INET_FRAG_COMPLETE)
goto out;
ipq_kill(qp);
__IP_INC_STATS(net, IPSTATS_MIB_REASMFAILS);
if (!inet_frag_evicting(&qp->q)) {
struct sk_buff *clone, *head = qp->q.fragments;
const struct iphdr *iph;
int err;
__IP_INC_STATS(net, IPSTATS_MIB_REASMTIMEOUT);
if (!(qp->q.flags & INET_FRAG_FIRST_IN) || !qp->q.fragments)
goto out;
head->dev = dev_get_by_index_rcu(net, qp->iif);
if (!head->dev)
goto out;
/* skb has no dst, perform route lookup again */
iph = ip_hdr(head);
err = ip_route_input_noref(head, iph->daddr, iph->saddr,
iph->tos, head->dev);
if (err)
goto out;
/* Only an end host needs to send an ICMP
* "Fragment Reassembly Timeout" message, per RFC792.
*/
if (frag_expire_skip_icmp(qp->user) &&
(skb_rtable(head)->rt_type != RTN_LOCAL))
goto out;
clone = skb_clone(head, GFP_ATOMIC);
/* Send an ICMP "Fragment Reassembly Timeout" message. */
if (clone) {
spin_unlock(&qp->q.lock);
icmp_send(clone, ICMP_TIME_EXCEEDED,
ICMP_EXC_FRAGTIME, 0);
consume_skb(clone);
goto out_rcu_unlock;
}
}
out:
spin_unlock(&qp->q.lock);
out_rcu_unlock:
rcu_read_unlock();
ipq_put(qp);
}
示例13: ipip_err
//.........这里部分代码省略.........
return;
case ICMP_PARAMETERPROB:
if (skb->h.icmph->un.gateway < hlen)
return;
/* So... This guy found something strange INSIDE encapsulated
packet. Well, he is fool, but what can we do ?
*/
rel_type = ICMP_PARAMETERPROB;
rel_info = skb->h.icmph->un.gateway - hlen;
break;
case ICMP_DEST_UNREACH:
switch (code) {
case ICMP_SR_FAILED:
case ICMP_PORT_UNREACH:
/* Impossible event. */
return;
case ICMP_FRAG_NEEDED:
/* And it is the only really necessary thing :-) */
rel_info = ntohs(skb->h.icmph->un.frag.mtu);
if (rel_info < hlen+68)
return;
rel_info -= hlen;
/* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */
if (rel_info > ntohs(eiph->tot_len))
return;
break;
default:
/* All others are translated to HOST_UNREACH.
rfc2003 contains "deep thoughts" about NET_UNREACH,
I believe, it is just ether pollution. --ANK
*/
rel_type = ICMP_DEST_UNREACH;
rel_code = ICMP_HOST_UNREACH;
break;
}
break;
case ICMP_TIME_EXCEEDED:
if (code != ICMP_EXC_TTL)
return;
break;
}
/* Prepare fake skb to feed it to icmp_send */
skb2 = skb_clone(skb, GFP_ATOMIC);
if (skb2 == NULL)
return;
dst_release(skb2->dst);
skb2->dst = NULL;
skb_pull(skb2, skb->data - (u8*)eiph);
skb2->nh.raw = skb2->data;
/* Try to guess incoming interface */
if (ip_route_output(&rt, eiph->saddr, 0, RT_TOS(eiph->tos), 0)) {
kfree_skb(skb2);
return;
}
skb2->dev = rt->u.dst.dev;
/* route "incoming" packet */
if (rt->rt_flags&RTCF_LOCAL) {
ip_rt_put(rt);
rt = NULL;
if (ip_route_output(&rt, eiph->daddr, eiph->saddr, eiph->tos, 0) ||
rt->u.dst.dev->type != ARPHRD_IPGRE) {
ip_rt_put(rt);
kfree_skb(skb2);
return;
}
} else {
ip_rt_put(rt);
if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, skb2->dev) ||
skb2->dst->dev->type != ARPHRD_IPGRE) {
kfree_skb(skb2);
return;
}
}
/* change mtu on this route */
if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
if (rel_info > skb2->dst->pmtu) {
kfree_skb(skb2);
return;
}
skb2->dst->pmtu = rel_info;
rel_info = htonl(rel_info);
} else if (type == ICMP_TIME_EXCEEDED) {
struct ip_tunnel *t = (struct ip_tunnel*)skb2->dev->priv;
if (t->parms.iph.ttl) {
rel_type = ICMP_DEST_UNREACH;
rel_code = ICMP_HOST_UNREACH;
}
}
icmp_send(skb2, rel_type, rel_code, rel_info);
kfree_skb(skb2);
return;
#endif
}
示例14: ipgre_rcv
//.........这里部分代码省略.........
}
offset += 4;
}
if (flags&GRE_KEY) {
key = *(__be32*)(h + offset);
offset += 4;
}
if (flags&GRE_SEQ) {
seqno = ntohl(*(__be32*)(h + offset));
offset += 4;
}
}
gre_proto = *(__be16 *)(h + 2);
read_lock(&ipgre_lock);
if ((tunnel = ipgre_tunnel_lookup(skb->dev,
iph->saddr, iph->daddr, key,
gre_proto))) {
struct net_device_stats *stats = &tunnel->dev->stats;
secpath_reset(skb);
skb->protocol = gre_proto;
/* WCCP version 1 and 2 protocol decoding.
* - Change protocol to IP
* - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
*/
if (flags == 0 && gre_proto == htons(ETH_P_WCCP)) {
skb->protocol = htons(ETH_P_IP);
if ((*(h + offset) & 0xF0) != 0x40)
offset += 4;
}
skb->mac_header = skb->network_header;
__pskb_pull(skb, offset);
skb_postpull_rcsum(skb, skb_transport_header(skb), offset);
skb->pkt_type = PACKET_HOST;
#ifdef CONFIG_NET_IPGRE_BROADCAST
if (ipv4_is_multicast(iph->daddr)) {
/* Looped back packet, drop it! */
if (skb_rtable(skb)->fl.iif == 0)
goto drop;
stats->multicast++;
skb->pkt_type = PACKET_BROADCAST;
}
#endif
if (((flags&GRE_CSUM) && csum) ||
(!(flags&GRE_CSUM) && tunnel->parms.i_flags&GRE_CSUM)) {
stats->rx_crc_errors++;
stats->rx_errors++;
goto drop;
}
if (tunnel->parms.i_flags&GRE_SEQ) {
if (!(flags&GRE_SEQ) ||
(tunnel->i_seqno && (s32)(seqno - tunnel->i_seqno) < 0)) {
stats->rx_fifo_errors++;
stats->rx_errors++;
goto drop;
}
tunnel->i_seqno = seqno + 1;
}
len = skb->len;
/* Warning: All skb pointers will be invalidated! */
if (tunnel->dev->type == ARPHRD_ETHER) {
if (!pskb_may_pull(skb, ETH_HLEN)) {
stats->rx_length_errors++;
stats->rx_errors++;
goto drop;
}
iph = ip_hdr(skb);
skb->protocol = eth_type_trans(skb, tunnel->dev);
skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
}
stats->rx_packets++;
stats->rx_bytes += len;
skb->dev = tunnel->dev;
skb_dst_drop(skb);
nf_reset(skb);
skb_reset_network_header(skb);
ipgre_ecn_decapsulate(iph, skb);
netif_rx(skb);
read_unlock(&ipgre_lock);
return(0);
}
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
drop:
read_unlock(&ipgre_lock);
drop_nolock:
kfree_skb(skb);
return(0);
}
示例15: ip_forward
int ip_forward(struct sk_buff *skb)
{
struct net_device *dev2; /* Output device */
struct iphdr *iph; /* Our header */
struct rtable *rt; /* Route we use */
struct ip_options * opt = &(IPCB(skb)->opt);
unsigned short mtu;
if (IPCB(skb)->opt.router_alert && ip_call_ra_chain(skb))
return NET_RX_SUCCESS;
if (skb->pkt_type != PACKET_HOST)
goto drop;
skb->ip_summed = CHECKSUM_NONE;
/*
* According to the RFC, we must first decrease the TTL field. If
* that reaches zero, we must reply an ICMP control message telling
* that the packet's lifetime expired.
*/
iph = skb->nh.iph;
rt = (struct rtable*)skb->dst;
if (iph->ttl <= 1)
goto too_many_hops;
if (opt->is_strictroute && rt->rt_dst != rt->rt_gateway)
goto sr_failed;
/*
* Having picked a route we can now send the frame out
* after asking the firewall permission to do so.
*/
skb->priority = rt_tos2priority(iph->tos);
dev2 = rt->u.dst.dev;
mtu = rt->u.dst.pmtu;
/*
* We now generate an ICMP HOST REDIRECT giving the route
* we calculated.
*/
if (rt->rt_flags&RTCF_DOREDIRECT && !opt->srr)
ip_rt_send_redirect(skb);
/* We are about to mangle packet. Copy it! */
if (skb_cow(skb, dev2->hard_header_len))
goto drop;
iph = skb->nh.iph;
/* Decrease ttl after skb cow done */
ip_decrease_ttl(iph);
/*
* We now may allocate a new buffer, and copy the datagram into it.
* If the indicated interface is up and running, kick it.
*/
if (skb->len > mtu && (ntohs(iph->frag_off) & IP_DF))
goto frag_needed;
#ifdef CONFIG_IP_ROUTE_NAT
if (rt->rt_flags & RTCF_NAT) {
if (ip_do_nat(skb)) {
kfree_skb(skb);
return NET_RX_BAD;
}
}
#endif
return NF_HOOK(PF_INET, NF_IP_FORWARD, skb, skb->dev, dev2,
ip_forward_finish);
frag_needed:
IP_INC_STATS_BH(IpFragFails);
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
goto drop;
sr_failed:
/*
* Strict routing permits no gatewaying
*/
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_SR_FAILED, 0);
goto drop;
too_many_hops:
/* Tell the sender its packet died... */
icmp_send(skb, ICMP_TIME_EXCEEDED, ICMP_EXC_TTL, 0);
drop:
kfree_skb(skb);
return NET_RX_DROP;
}