@@ -2574,11 +2574,10 @@ struct rtable *ip_route_output_flow(struct net *net, struct flowi4 *flp4,
2574
2574
EXPORT_SYMBOL_GPL (ip_route_output_flow );
2575
2575
2576
2576
/* called with rcu_read_lock held */
2577
- static int rt_fill_info (struct net * net , __be32 dst , __be32 src , u32 table_id ,
2578
- struct flowi4 * fl4 , struct sk_buff * skb , u32 portid ,
2579
- u32 seq )
2577
+ static int rt_fill_info (struct net * net , __be32 dst , __be32 src ,
2578
+ struct rtable * rt , u32 table_id , struct flowi4 * fl4 ,
2579
+ struct sk_buff * skb , u32 portid , u32 seq )
2580
2580
{
2581
- struct rtable * rt = skb_rtable (skb );
2582
2581
struct rtmsg * r ;
2583
2582
struct nlmsghdr * nlh ;
2584
2583
unsigned long expires = 0 ;
@@ -2674,7 +2673,7 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, u32 table_id,
2674
2673
}
2675
2674
} else
2676
2675
#endif
2677
- if (nla_put_u32 (skb , RTA_IIF , skb -> dev -> ifindex ))
2676
+ if (nla_put_u32 (skb , RTA_IIF , fl4 -> flowi4_iif ))
2678
2677
goto nla_put_failure ;
2679
2678
}
2680
2679
@@ -2689,43 +2688,93 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, u32 table_id,
2689
2688
return - EMSGSIZE ;
2690
2689
}
2691
2690
2691
+ static struct sk_buff * inet_rtm_getroute_build_skb (__be32 src , __be32 dst ,
2692
+ u8 ip_proto , __be16 sport ,
2693
+ __be16 dport )
2694
+ {
2695
+ struct sk_buff * skb ;
2696
+ struct iphdr * iph ;
2697
+
2698
+ skb = alloc_skb (NLMSG_GOODSIZE , GFP_KERNEL );
2699
+ if (!skb )
2700
+ return NULL ;
2701
+
2702
+ /* Reserve room for dummy headers, this skb can pass
2703
+ * through good chunk of routing engine.
2704
+ */
2705
+ skb_reset_mac_header (skb );
2706
+ skb_reset_network_header (skb );
2707
+ skb -> protocol = htons (ETH_P_IP );
2708
+ iph = skb_put (skb , sizeof (struct iphdr ));
2709
+ iph -> protocol = ip_proto ;
2710
+ iph -> saddr = src ;
2711
+ iph -> daddr = dst ;
2712
+ iph -> version = 0x4 ;
2713
+ iph -> frag_off = 0 ;
2714
+ iph -> ihl = 0x5 ;
2715
+ skb_set_transport_header (skb , skb -> len );
2716
+
2717
+ switch (iph -> protocol ) {
2718
+ case IPPROTO_UDP : {
2719
+ struct udphdr * udph ;
2720
+
2721
+ udph = skb_put_zero (skb , sizeof (struct udphdr ));
2722
+ udph -> source = sport ;
2723
+ udph -> dest = dport ;
2724
+ udph -> len = sizeof (struct udphdr );
2725
+ udph -> check = 0 ;
2726
+ break ;
2727
+ }
2728
+ case IPPROTO_TCP : {
2729
+ struct tcphdr * tcph ;
2730
+
2731
+ tcph = skb_put_zero (skb , sizeof (struct tcphdr ));
2732
+ tcph -> source = sport ;
2733
+ tcph -> dest = dport ;
2734
+ tcph -> doff = sizeof (struct tcphdr ) / 4 ;
2735
+ tcph -> rst = 1 ;
2736
+ tcph -> check = ~tcp_v4_check (sizeof (struct tcphdr ),
2737
+ src , dst , 0 );
2738
+ break ;
2739
+ }
2740
+ case IPPROTO_ICMP : {
2741
+ struct icmphdr * icmph ;
2742
+
2743
+ icmph = skb_put_zero (skb , sizeof (struct icmphdr ));
2744
+ icmph -> type = ICMP_ECHO ;
2745
+ icmph -> code = 0 ;
2746
+ }
2747
+ }
2748
+
2749
+ return skb ;
2750
+ }
2751
+
2692
2752
static int inet_rtm_getroute (struct sk_buff * in_skb , struct nlmsghdr * nlh ,
2693
2753
struct netlink_ext_ack * extack )
2694
2754
{
2695
2755
struct net * net = sock_net (in_skb -> sk );
2696
- struct rtmsg * rtm ;
2697
2756
struct nlattr * tb [RTA_MAX + 1 ];
2757
+ u32 table_id = RT_TABLE_MAIN ;
2758
+ __be16 sport = 0 , dport = 0 ;
2698
2759
struct fib_result res = {};
2760
+ u8 ip_proto = IPPROTO_UDP ;
2699
2761
struct rtable * rt = NULL ;
2762
+ struct sk_buff * skb ;
2763
+ struct rtmsg * rtm ;
2700
2764
struct flowi4 fl4 ;
2701
2765
__be32 dst = 0 ;
2702
2766
__be32 src = 0 ;
2767
+ kuid_t uid ;
2703
2768
u32 iif ;
2704
2769
int err ;
2705
2770
int mark ;
2706
- struct sk_buff * skb ;
2707
- u32 table_id = RT_TABLE_MAIN ;
2708
- kuid_t uid ;
2709
2771
2710
2772
err = nlmsg_parse (nlh , sizeof (* rtm ), tb , RTA_MAX , rtm_ipv4_policy ,
2711
2773
extack );
2712
2774
if (err < 0 )
2713
- goto errout ;
2775
+ return err ;
2714
2776
2715
2777
rtm = nlmsg_data (nlh );
2716
-
2717
- skb = alloc_skb (NLMSG_GOODSIZE , GFP_KERNEL );
2718
- if (!skb ) {
2719
- err = - ENOBUFS ;
2720
- goto errout ;
2721
- }
2722
-
2723
- /* Reserve room for dummy headers, this skb can pass
2724
- through good chunk of routing engine.
2725
- */
2726
- skb_reset_mac_header (skb );
2727
- skb_reset_network_header (skb );
2728
-
2729
2778
src = tb [RTA_SRC ] ? nla_get_in_addr (tb [RTA_SRC ]) : 0 ;
2730
2779
dst = tb [RTA_DST ] ? nla_get_in_addr (tb [RTA_DST ]) : 0 ;
2731
2780
iif = tb [RTA_IIF ] ? nla_get_u32 (tb [RTA_IIF ]) : 0 ;
@@ -2735,14 +2784,22 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
2735
2784
else
2736
2785
uid = (iif ? INVALID_UID : current_uid ());
2737
2786
2738
- /* Bugfix: need to give ip_route_input enough of an IP header to
2739
- * not gag.
2740
- */
2741
- ip_hdr (skb )-> protocol = IPPROTO_UDP ;
2742
- ip_hdr (skb )-> saddr = src ;
2743
- ip_hdr (skb )-> daddr = dst ;
2787
+ if (tb [RTA_IP_PROTO ]) {
2788
+ err = rtm_getroute_parse_ip_proto (tb [RTA_IP_PROTO ],
2789
+ & ip_proto , extack );
2790
+ if (err )
2791
+ return err ;
2792
+ }
2793
+
2794
+ if (tb [RTA_SPORT ])
2795
+ sport = nla_get_be16 (tb [RTA_SPORT ]);
2744
2796
2745
- skb_reserve (skb , MAX_HEADER + sizeof (struct iphdr ));
2797
+ if (tb [RTA_DPORT ])
2798
+ dport = nla_get_be16 (tb [RTA_DPORT ]);
2799
+
2800
+ skb = inet_rtm_getroute_build_skb (src , dst , ip_proto , sport , dport );
2801
+ if (!skb )
2802
+ return - ENOBUFS ;
2746
2803
2747
2804
memset (& fl4 , 0 , sizeof (fl4 ));
2748
2805
fl4 .daddr = dst ;
@@ -2751,6 +2808,11 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
2751
2808
fl4 .flowi4_oif = tb [RTA_OIF ] ? nla_get_u32 (tb [RTA_OIF ]) : 0 ;
2752
2809
fl4 .flowi4_mark = mark ;
2753
2810
fl4 .flowi4_uid = uid ;
2811
+ if (sport )
2812
+ fl4 .fl4_sport = sport ;
2813
+ if (dport )
2814
+ fl4 .fl4_dport = dport ;
2815
+ fl4 .flowi4_proto = ip_proto ;
2754
2816
2755
2817
rcu_read_lock ();
2756
2818
@@ -2760,10 +2822,10 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
2760
2822
dev = dev_get_by_index_rcu (net , iif );
2761
2823
if (!dev ) {
2762
2824
err = - ENODEV ;
2763
- goto errout_free ;
2825
+ goto errout_rcu ;
2764
2826
}
2765
2827
2766
- skb -> protocol = htons ( ETH_P_IP );
2828
+ fl4 . flowi4_iif = iif ; /* for rt_fill_info */
2767
2829
skb -> dev = dev ;
2768
2830
skb -> mark = mark ;
2769
2831
err = ip_route_input_rcu (skb , dst , src , rtm -> rtm_tos ,
@@ -2783,42 +2845,48 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
2783
2845
}
2784
2846
2785
2847
if (err )
2786
- goto errout_free ;
2848
+ goto errout_rcu ;
2787
2849
2788
2850
if (rtm -> rtm_flags & RTM_F_NOTIFY )
2789
2851
rt -> rt_flags |= RTCF_NOTIFY ;
2790
2852
2791
2853
if (rtm -> rtm_flags & RTM_F_LOOKUP_TABLE )
2792
2854
table_id = res .table ? res .table -> tb_id : 0 ;
2793
2855
2856
+ /* reset skb for netlink reply msg */
2857
+ skb_trim (skb , 0 );
2858
+ skb_reset_network_header (skb );
2859
+ skb_reset_transport_header (skb );
2860
+ skb_reset_mac_header (skb );
2861
+
2794
2862
if (rtm -> rtm_flags & RTM_F_FIB_MATCH ) {
2795
2863
if (!res .fi ) {
2796
2864
err = fib_props [res .type ].error ;
2797
2865
if (!err )
2798
2866
err = - EHOSTUNREACH ;
2799
- goto errout_free ;
2867
+ goto errout_rcu ;
2800
2868
}
2801
2869
err = fib_dump_info (skb , NETLINK_CB (in_skb ).portid ,
2802
2870
nlh -> nlmsg_seq , RTM_NEWROUTE , table_id ,
2803
2871
rt -> rt_type , res .prefix , res .prefixlen ,
2804
2872
fl4 .flowi4_tos , res .fi , 0 );
2805
2873
} else {
2806
- err = rt_fill_info (net , dst , src , table_id , & fl4 , skb ,
2874
+ err = rt_fill_info (net , dst , src , rt , table_id , & fl4 , skb ,
2807
2875
NETLINK_CB (in_skb ).portid , nlh -> nlmsg_seq );
2808
2876
}
2809
2877
if (err < 0 )
2810
- goto errout_free ;
2878
+ goto errout_rcu ;
2811
2879
2812
2880
rcu_read_unlock ();
2813
2881
2814
2882
err = rtnl_unicast (skb , net , NETLINK_CB (in_skb ).portid );
2815
- errout :
2816
- return err ;
2817
2883
2818
2884
errout_free :
2885
+ return err ;
2886
+ errout_rcu :
2819
2887
rcu_read_unlock ();
2820
2888
kfree_skb (skb );
2821
- goto errout ;
2889
+ goto errout_free ;
2822
2890
}
2823
2891
2824
2892
void ip_rt_multicast_event (struct in_device * in_dev )
0 commit comments