1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
| 774 struct fib_info *fib_create_info(struct fib_config *cfg) 775 { 776 int err; 777 struct fib_info *fi = NULL; 778 struct fib_info *ofi; 779 int nhs = 1; 780 struct net *net = cfg->fc_nlinfo.nl_net; 781 782 if (cfg->fc_type > RTN_MAX) 783 goto err_inval; 784 785 786 if (fib_props[cfg->fc_type].scope > cfg->fc_scope) 787 goto err_inval; 788 789 #ifdef CONFIG_IP_ROUTE_MULTIPATH 790 if (cfg->fc_mp) { 791 nhs = fib_count_nexthops(cfg->fc_mp, cfg->fc_mp_len); 792 if (nhs == 0) 793 goto err_inval; 794 } 795 #endif 796 797 err = -ENOBUFS; 798 if (fib_info_cnt >= fib_info_hash_size) { 799 unsigned int new_size = fib_info_hash_size << 1; 800 struct hlist_head *new_info_hash; 801 struct hlist_head *new_laddrhash; 802 unsigned int bytes; 803 804 if (!new_size) 805 new_size = 16; 806 bytes = new_size * sizeof(struct hlist_head *); 807 new_info_hash = fib_info_hash_alloc(bytes); 808 new_laddrhash = fib_info_hash_alloc(bytes); 809 if (!new_info_hash || !new_laddrhash) { 810 fib_info_hash_free(new_info_hash, bytes); 811 fib_info_hash_free(new_laddrhash, bytes); 812 } else 813 fib_info_hash_move(new_info_hash, new_laddrhash, new_size); 814 815 if (!fib_info_hash_size) 816 goto failure; 817 } 818 819 fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL); 820 if (fi == NULL) 821 goto failure; 822 if (cfg->fc_mx) { 823 fi->fib_metrics = kzalloc(sizeof(u32) * RTAX_MAX, GFP_KERNEL); 824 if (!fi->fib_metrics) 825 goto failure; 826 } else 827 fi->fib_metrics = (u32 *) dst_default_metrics; 828 fib_info_cnt++; 829 830 fi->fib_net = hold_net(net); 831 fi->fib_protocol = cfg->fc_protocol; 832 fi->fib_scope = cfg->fc_scope; 833 fi->fib_flags = cfg->fc_flags; 834 fi->fib_priority = cfg->fc_priority; 835 fi->fib_prefsrc = cfg->fc_prefsrc; 836 fi->fib_type = cfg->fc_type; 837 838 fi->fib_nhs = nhs; 839 change_nexthops(fi) { 840 nexthop_nh->nh_parent = fi; 841 nexthop_nh->nh_pcpu_rth_output = alloc_percpu(struct rtable __rcu *); 842 if (!nexthop_nh->nh_pcpu_rth_output) 843 goto failure; 844 } endfor_nexthops(fi) 845 846 if (cfg->fc_mx) { 847 struct nlattr *nla; 848 int remaining; 849 850 nla_for_each_attr(nla, cfg->fc_mx, cfg->fc_mx_len, remaining) { 851 int type = nla_type(nla); 852 853 if (type) { 854 u32 val; 855 856 if (type > RTAX_MAX) 857 goto err_inval; 858 val = nla_get_u32(nla); 859 if (type == RTAX_ADVMSS && val > 65535 - 40) 860 val = 65535 - 40; 861 if (type == RTAX_MTU && val > 65535 - 15) 862 val = 65535 - 15; 863 fi->fib_metrics[type - 1] = val; 864 } 865 } 866 } 867 868 if (cfg->fc_mp) { 869 #ifdef CONFIG_IP_ROUTE_MULTIPATH 870 err = fib_get_nhs(fi, cfg->fc_mp, cfg->fc_mp_len, cfg); 871 if (err != 0) 872 goto failure; 873 if (cfg->fc_oif && fi->fib_nh->nh_oif != cfg->fc_oif) 874 goto err_inval; 875 if (cfg->fc_gw && fi->fib_nh->nh_gw != cfg->fc_gw) 876 goto err_inval; 877 #ifdef CONFIG_IP_ROUTE_CLASSID 878 if (cfg->fc_flow && fi->fib_nh->nh_tclassid != cfg->fc_flow) 879 goto err_inval; 880 #endif 881 #else 882 goto err_inval; 883 #endif 884 } else { 885 struct fib_nh *nh = fi->fib_nh; 886 887 nh->nh_oif = cfg->fc_oif; 888 nh->nh_gw = cfg->fc_gw; 889 nh->nh_flags = cfg->fc_flags; 890 #ifdef CONFIG_IP_ROUTE_CLASSID 891 nh->nh_tclassid = cfg->fc_flow; 892 if (nh->nh_tclassid) 893 fi->fib_net->ipv4.fib_num_tclassid_users++; 894 #endif 895 #ifdef CONFIG_IP_ROUTE_MULTIPATH 896 nh->nh_weight = 1; 897 #endif 898 } 899 900 if (fib_props[cfg->fc_type].error) { 901 if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp) 902 goto err_inval; 903 goto link_it; 904 } else { 905 switch (cfg->fc_type) { 906 case RTN_UNICAST: 907 case RTN_LOCAL: 908 case RTN_BROADCAST: 909 case RTN_ANYCAST: 910 case RTN_MULTICAST: 911 break; 912 default: 913 goto err_inval; 914 } 915 } 916 917 if (cfg->fc_scope > RT_SCOPE_HOST) 918 goto err_inval; 919 920 if (cfg->fc_scope == RT_SCOPE_HOST) { 921 struct fib_nh *nh = fi->fib_nh; 922 923 924 if (nhs != 1 || nh->nh_gw) 925 goto err_inval; 926 nh->nh_scope = RT_SCOPE_NOWHERE; 927 nh->nh_dev = dev_get_by_index(net, fi->fib_nh->nh_oif); 928 err = -ENODEV; 929 if (nh->nh_dev == NULL) 930 goto failure; 931 } else { 932 change_nexthops(fi) { 933 err = fib_check_nh(cfg, fi, nexthop_nh); 934 if (err != 0) 935 goto failure; 936 } endfor_nexthops(fi) 937 } 938 939 if (fi->fib_prefsrc) { 940 if (cfg->fc_type != RTN_LOCAL || !cfg->fc_dst || 941 fi->fib_prefsrc != cfg->fc_dst) 942 if (inet_addr_type(net, fi->fib_prefsrc) != RTN_LOCAL) 943 goto err_inval; 944 } 945 946 change_nexthops(fi) { 947 fib_info_update_nh_saddr(net, nexthop_nh); 948 } endfor_nexthops(fi) 949 950 link_it: 951 ofi = fib_find_info(fi); 952 if (ofi) { 953 fi->fib_dead = 1; 954 free_fib_info(fi); 955 ofi->fib_treeref++; 956 return ofi; 957 } 958 959 fi->fib_treeref++; 960 atomic_inc(&fi->fib_clntref); 961 spin_lock_bh(&fib_info_lock); 962 hlist_add_head(&fi->fib_hash, 963 &fib_info_hash[fib_info_hashfn(fi)]); 964 if (fi->fib_prefsrc) { 965 struct hlist_head *head; 966 967 head = &fib_info_laddrhash[fib_laddr_hashfn(fi->fib_prefsrc)]; 968 hlist_add_head(&fi->fib_lhash, head); 969 } 970 change_nexthops(fi) { 971 struct hlist_head *head; 972 unsigned int hash; 973 974 if (!nexthop_nh->nh_dev) 975 continue; 976 hash = fib_devindex_hashfn(nexthop_nh->nh_dev->ifindex); 977 head = &fib_info_devhash[hash]; 978 hlist_add_head(&nexthop_nh->nh_hash, head); 979 } endfor_nexthops(fi) 980 spin_unlock_bh(&fib_info_lock); 981 return fi; 982 983 err_inval: 984 err = -EINVAL; 985 986 failure: 987 if (fi) { 988 fi->fib_dead = 1; 989 free_fib_info(fi); 990 } 991 992 return ERR_PTR(err); 993 }
|