📄 linux-kernel.diff
字号:
+ struct icmphdr *icmph;+ struct sk_buff *nskb;+ unsigned char *data;+ struct rtable *rt;+ struct iphdr *iph;++ unsigned int icmp_start = 0;+ unsigned int len = 0;+ unsigned int real;+ unsigned int max;+ unsigned int height;+ int pull;++ /* find the distance to the bottom of the MPLS stack */+ pull = mpls_find_payload(skb);+ if (pull < 0)+ goto error_0;++ if (!skb_pull(skb, pull))+ goto error_0;++ height = skb->data - MPLSCB(skb)->top_of_stack;++ /* now where at the payload, for now we're+ * assuming this is IPv4+ */+ skb->nh.raw = skb->data;++ /* buid a new skb, that will be big enough to hold+ * a maximum of 576 bytes (RFC792)+ */+ if ((skb->len + skb_tailroom(skb)) < 576) {+ nskb = skb_copy_expand(skb, skb_headroom(skb),+ (576 + 16) - skb->len, GFP_ATOMIC);+ } else {+ nskb = skb_copy(skb, GFP_ATOMIC);+ }++ if (!nskb)+ goto error_0;++ /* I don't handle IP options */+ if (nskb->nh.iph->ihl > 5) {+ printk("Options!!!!\n");+ goto error_1;+ }++ memset(buf, 0, sizeof(buf));++ /* point to the buf, we'll build our ICMP message there+ * then copy to nskb when we're done+ */+ iph = (struct iphdr*)&buf[len];+ iph->version = 4;+ iph->ihl = 5;+ iph->tos = nskb->nh.iph->tos;+ iph->tot_len = 0;+ iph->id = 0;+ iph->frag_off = 0;+ iph->ttl = 255;+ iph->protocol = IPPROTO_ICMP;+ iph->check = 0;+ iph->saddr = nskb->nh.iph->daddr;+ iph->daddr = nskb->nh.iph->saddr;+ len += sizeof(struct iphdr);++ icmp_start = len;+ icmph = (struct icmphdr*)&buf[len];+ icmph->checksum = 0;+ icmph->un.gateway = icmp_data;++ switch (type) {+ case ICMP_TIME_EXCEEDED:+ icmph->type = ICMP_TIME_EXCEEDED;+ icmph->code = ICMP_EXC_TTL;+ break;+ case ICMP_DEST_UNREACH:+ icmph->type = ICMP_DEST_UNREACH;+ icmph->code = ICMP_FRAG_NEEDED;+ break;+ default:+ BUG_ON(1);+ break;+ }+ len += sizeof(struct icmphdr);++ data = &buf[len];+ if (mpls) {+ max = 128;+ } else {+ max = 576 - len;+ }+ real = (nskb->len > max) ? max : skb->len;+ memcpy(data, nskb->data, real);++ if (!mpls) {+ len += real;+ } else {+ struct mpls_icmp_common *common;+ struct mpls_icmp_object *object;+ unsigned char *mpls_data = NULL;+ unsigned int obj_start = 0;+ unsigned int mpls_start = 0;++ len += 128;++ mpls_start = len;+ common = (struct mpls_icmp_common*)&buf[len];+ common->version = 2;+ common->res1 = 0;+ common->res2 = 0;+ common->check = 0;+ len += sizeof(struct mpls_icmp_common);++ obj_start = len;+ object = (struct mpls_icmp_object*)&buf[len];+ object->length = 0;+ object->class = 1;+ object->type = 1;+ len += sizeof(struct mpls_icmp_object);++ mpls_data = &buf[len];+ memcpy(mpls_data, MPLSCB(skb)->top_of_stack, height);+ len += height;++ object->length = htons(len - obj_start);+ common->check = csum_fold (csum_partial ((char*)common,+ len - mpls_start, 0));+ }++ iph->tot_len = htons(len);+ ip_send_check(iph);+ icmph->checksum = csum_fold (csum_partial ((char*)icmph,+ len - icmp_start, 0));++ nskb->len = len;+ memcpy(nskb->data, buf, nskb->len);+ nskb->tail = nskb->data + nskb->len;++ nskb->ip_summed = CHECKSUM_NONE;+ nskb->csum = 0;++ {+ struct flowi fl = {+ .nl_u = { .ip4_u = {+ .daddr = iph->daddr,+ .saddr = iph->saddr,+ .tos = RT_TOS(iph->tos) } },+ .proto = IPPROTO_ICMP };++ if (ip_route_output_key(&rt, &fl))+ goto error_1;+ }++ if (nskb->dst)+ dst_release(nskb->dst);++ nskb->dst = &rt->u.dst;++ return nskb;++error_1:+ kfree_skb(nskb);+error_0:+ return NULL;+}++/* Policy decision, several options:+ *+ * 1) Silently discard+ * 2) Pops all MPLS headers, use resulting upper-layer+ * protocol packet to generate ICMP.+ * 3) Walk down MPLS headers to upper-layer header,+ * generate ICMP using that and then prepend+ * IDENTICAL MPLS header stack to ICMP packet.+ *+ * Problem with #2 is that there may be no route to+ * upper-level packet source for us to use. (f.e. we+ * are switching VPN packets that we have no routes to).+ *+ * Option #3 should work even in those cases, because it+ * is more likely that egress of this MPLS path knows how+ * to route such packets back to source. It should also+ * not be susceptible to loops in MPLS fabric, since one+ * never responds to ICMP with ICMP. It is deliberate+ * assumption made about upper-layer protocol.+ */+static int mpls4_ttl_expired(struct sk_buff **skb)+{+ struct sk_buff *nskb;++ if ((nskb = mpls4_build_icmp(*skb, ICMP_TIME_EXCEEDED, 0, 1)))+ if (dst_output(nskb))+ kfree_skb(nskb);++ /* make sure the MPLS stack frees the original skb! */+ return NET_RX_DROP;+}++static int mpls4_mtu_exceeded(struct sk_buff **skb, int mtu)+{+ struct sk_buff *nskb;++ if ((nskb = mpls4_build_icmp(*skb, ICMP_DEST_UNREACH, htonl(mtu), 0)))+ if (dst_output(nskb))+ kfree_skb(nskb);++ /* make sure the MPLS stack frees the original skb! */+ return MPLS_RESULT_DROP;+}++static int mpls4_local_deliver(struct sk_buff *skb)+{+ skb->protocol = htons(ETH_P_IP);+ memset(skb->cb, 0, sizeof(skb->cb));+ dst_release(skb->dst);+ skb->dst = NULL;+ return ip_rcv(skb, skb->dev, NULL);+}++static int mpls4_nexthop_resolve(struct neighbour **np, struct sockaddr *sock_addr, struct net_device *dev)+{+ struct sockaddr_in *addr = (struct sockaddr_in *) sock_addr;+ u32 saddr = addr->sin_addr.s_addr;+ struct flowi fl = { .oif = dev->ifindex,+ .nl_u = { .ip4_u = { .daddr = saddr } } };+ struct rtable *rp;+ int err;++ if (addr->sin_family != AF_INET)+ return -EINVAL;++ if (inet_addr_type(saddr) != RTN_UNICAST)+ return -EINVAL;++ err = __ip_route_output_key(&rp, &fl);+ if (err)+ return err;++ /* If routing cache stops to automatically bind output routes+ * to ARP cache, we will have to make arp_bind_neighbour() ourselves.+ */+ if (!rp->u.dst.neighbour)+ BUG();++ *np = neigh_clone(rp->u.dst.neighbour);+ ip_rt_put(rp);++ return err;+}++static struct mpls_prot_driver mpls4_driver = {+ .prot_num = AF_INET,+ .cache_flush = mpls4_cache_flush,+ .set_ttl = mpls4_set_ttl,+ .get_ttl = mpls4_get_ttl,+ .change_dsfield = mpls4_change_dsfield,+ .get_dsfield = mpls4_get_dsfield,+ .ttl_expired = mpls4_ttl_expired,+ .mtu_exceeded = mpls4_mtu_exceeded,+ .local_deliver = mpls4_local_deliver,+ .nexthop_resolve = mpls4_nexthop_resolve,+ .owner = THIS_MODULE,+};++static int __init mpls4_init(void)+{+ struct mpls_instr_elem instr[2];+ struct mpls_label ml;+ struct mpls_ilm *ilm;+ int result = mpls_register_prot(&mpls4_driver);++ if (result)+ return result;++ ml.ml_type = MPLS_LABEL_GEN;+ ml.u.ml_gen = MPLS_IPV4_EXPLICIT_NULL;++ instr[0].mir_direction = MPLS_IN;+ instr[0].mir_opcode = MPLS_OP_POP;+ instr[1].mir_direction = MPLS_IN;+ instr[1].mir_opcode = MPLS_OP_DLV;++ ilm = mpls_ilm_dst_alloc(0, &ml, AF_INET, instr, 2);+ if (!ilm)+ return -ENOMEM;++ result = mpls_add_reserved_label(MPLS_IPV4_EXPLICIT_NULL, ilm);+ if (result) {+ ilm->u.dst.obsolete = 1;+ dst_free(&ilm->u.dst);+ return result;+ }++ return 0;+}++static void __exit mpls4_fini(void)+{+ struct mpls_ilm *ilm = mpls_del_reserved_label(MPLS_IPV4_EXPLICIT_NULL);+ mpls_unregister_prot(&mpls4_driver);++ if (ilm) {+ mpls_ilm_release(ilm);+ ilm->u.dst.obsolete = 1;+ call_rcu(&ilm->u.dst.rcu_head, dst_rcu_free);+ }+}++module_init(mpls4_init);+module_exit(mpls4_fini);diff -uNr linux-kernel/net/ipv4/netfilter/ipt_spec_nh.c mpls-kernel-1/net/ipv4/netfilter/ipt_spec_nh.c--- linux-kernel/net/ipv4/netfilter/ipt_spec_nh.c 1969-12-31 18:00:00.000000000 -0600+++ mpls-kernel-1/net/ipv4/netfilter/ipt_spec_nh.c 2005-01-05 01:10:18.000000000 -0600@@ -0,0 +1,73 @@+/* This is a module which is used for setting up a SKB to use a spec_nh. */+#include <linux/module.h>+#include <linux/skbuff.h>+#include <linux/ip.h>+#include <net/checksum.h>+#include <net/spec_nh.h>+#include <net/mpls.h>++#include <linux/netfilter_ipv4/ip_tables.h>+#include <linux/netfilter_ipv4/ipt_spec_nh.h>++MODULE_LICENSE("GPL");+MODULE_AUTHOR("James R. Leu <jle@mindspring.com>");+MODULE_DESCRIPTION("iptables spec_nh module");++static unsigned int+target(struct sk_buff **pskb,+ const struct net_device *in,+ const struct net_device *out,+ unsigned int hooknum,+ const void *targinfo,+ void *userinfo)+{+ const struct ipt_spec_nh_target_info *spec_nh_info = targinfo;+ struct spec_nh *spec_nh;++ spec_nh = spec_nh_find(spec_nh_info->proto);++ if (spec_nh)+ spec_nh->func((*pskb)->dst, spec_nh_info->data, spec_nh);++ return IPT_CONTINUE;+}++static int+checkentry(const char *tablename,+ const struct ipt_entry *e,+ void *targinfo,+ unsigned int targinfosize,+ unsigned int hook_mask)+{+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_spec_nh_target_info))) {+ printk(KERN_WARNING "spec_nh: targinfosize %u != %Zu\n",+ targinfosize,+ IPT_ALIGN(sizeof(struct ipt_spec_nh_target_info)));+ return 0;+ }++ return 1;+}++static struct ipt_target ipt_spec_nh_reg = {+ .name = "spec_nh",+ .target = target,+ .checkentry = checkentry,+ .me = THIS_MODULE,+};++static int __init init(void)+{+ if (ipt_register_target(&ipt_spec_nh_reg))+ return -EINVAL;++ return 0;+}++static void __exit fini(void)+{+ ipt_unregister_target(&ipt_spec_nh_reg);+}++module_init(init);+module_exit(fini);diff -uNr linux-kernel/net/ipv4/netfilter/Kconfig mpls-kernel-1/net/ipv4/netfilter/Kconfig--- linux-kernel/net/ipv4/netfilter/Kconfig 2004-10-22 13:40:46.000000000 -0500+++ mpls-kernel-1/net/ipv4/netfilter/Kconfig 2005-01-05 01:10:14.000000000 -0600@@ -585,6 +585,15 @@ To compile it as a module, choose M here. If unsure, say N. +config IP_NF_TARGET_SPEC_NH+ tristate "spec_nh target support"+ depends on IP_NF_IPTABLES+ help+ This option adds a `spec_nh' target, which allows you to set+ special nexthops.++ To compile it as a module, choose M here. If unsure, say N.+ config IP_NF_TARGET_CLASSIFY tristate "CLASSIFY target support" depends on IP_NF_MANGLEdiff -uNr linux-kernel/net/ipv4/netfilter/Makefile mpls-kernel-1/net/ipv4/netfilter/Makefile--- linux-kernel/net/ipv4/netfilter/Makefile 2004-10-22 13:40:46.000000000 -0500+++ mpls-kernel-1/net/ipv4/netfilter/Makefile 2005-01-05 01:10:14.000000000 -0600@@ -74,6 +74,7 @@ obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o+obj-$(CONFIG_IP_NF_TARGET_SPEC_NH) += ipt_spec_nh.o obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.odiff -uNr linux-kernel/net/ipv4/route.c mpls-kernel-1/net/ipv4/route.c--- linux-kernel/net/ipv4/route.c 2004-10-22 13:40:48.000000000 -0500+++ mpls-kernel-1/net/ipv4/route.c 2005-01-05 01:10:18.000000000 -0600@@ -103,6 +103,7 @@ #ifdef CONFIG_SYSCTL #include <linux/sysctl.h> #endif+#include <net/spec_nh.h> #define IP_MAX_MTU 0xFFF0 @@ -1416,6 +1417,7 @@ static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag) { struct fib_info *fi = res->fi;+ struct spec_nh *spec_nh; if (fi) { if (FIB_RES_GW(*res) &&@@ -1423,7 +1425,13 @@ rt->rt_gateway = FIB_RES_GW(*res); memcpy(rt->u.dst.metrics, fi->fib_metrics,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -