diff options
40 files changed, 839 insertions, 318 deletions
diff --git a/include/linux/atalk.h b/include/linux/atalk.h index 31d3fc25ccbd..09a1451c1159 100644 --- a/include/linux/atalk.h +++ b/include/linux/atalk.h | |||
| @@ -20,7 +20,7 @@ | |||
| 20 | #define SIOCATALKDIFADDR (SIOCPROTOPRIVATE + 0) | 20 | #define SIOCATALKDIFADDR (SIOCPROTOPRIVATE + 0) |
| 21 | 21 | ||
| 22 | struct atalk_addr { | 22 | struct atalk_addr { |
| 23 | __u16 s_net; | 23 | __be16 s_net; |
| 24 | __u8 s_node; | 24 | __u8 s_node; |
| 25 | }; | 25 | }; |
| 26 | 26 | ||
| @@ -33,8 +33,8 @@ struct sockaddr_at { | |||
| 33 | 33 | ||
| 34 | struct atalk_netrange { | 34 | struct atalk_netrange { |
| 35 | __u8 nr_phase; | 35 | __u8 nr_phase; |
| 36 | __u16 nr_firstnet; | 36 | __be16 nr_firstnet; |
| 37 | __u16 nr_lastnet; | 37 | __be16 nr_lastnet; |
| 38 | }; | 38 | }; |
| 39 | 39 | ||
| 40 | #ifdef __KERNEL__ | 40 | #ifdef __KERNEL__ |
| @@ -70,8 +70,8 @@ struct atalk_iface { | |||
| 70 | struct atalk_sock { | 70 | struct atalk_sock { |
| 71 | /* struct sock has to be the first member of atalk_sock */ | 71 | /* struct sock has to be the first member of atalk_sock */ |
| 72 | struct sock sk; | 72 | struct sock sk; |
| 73 | unsigned short dest_net; | 73 | __be16 dest_net; |
| 74 | unsigned short src_net; | 74 | __be16 src_net; |
| 75 | unsigned char dest_node; | 75 | unsigned char dest_node; |
| 76 | unsigned char src_node; | 76 | unsigned char src_node; |
| 77 | unsigned char dest_port; | 77 | unsigned char dest_port; |
| @@ -95,9 +95,9 @@ struct ddpehdr { | |||
| 95 | deh_hops:4, | 95 | deh_hops:4, |
| 96 | deh_len:10; | 96 | deh_len:10; |
| 97 | #endif | 97 | #endif |
| 98 | __u16 deh_sum; | 98 | __be16 deh_sum; |
| 99 | __u16 deh_dnet; | 99 | __be16 deh_dnet; |
| 100 | __u16 deh_snet; | 100 | __be16 deh_snet; |
| 101 | __u8 deh_dnode; | 101 | __u8 deh_dnode; |
| 102 | __u8 deh_snode; | 102 | __u8 deh_snode; |
| 103 | __u8 deh_dport; | 103 | __u8 deh_dport; |
| @@ -142,24 +142,24 @@ struct ddpshdr { | |||
| 142 | 142 | ||
| 143 | /* AppleTalk AARP headers */ | 143 | /* AppleTalk AARP headers */ |
| 144 | struct elapaarp { | 144 | struct elapaarp { |
| 145 | __u16 hw_type; | 145 | __be16 hw_type; |
| 146 | #define AARP_HW_TYPE_ETHERNET 1 | 146 | #define AARP_HW_TYPE_ETHERNET 1 |
| 147 | #define AARP_HW_TYPE_TOKENRING 2 | 147 | #define AARP_HW_TYPE_TOKENRING 2 |
| 148 | __u16 pa_type; | 148 | __be16 pa_type; |
| 149 | __u8 hw_len; | 149 | __u8 hw_len; |
| 150 | __u8 pa_len; | 150 | __u8 pa_len; |
| 151 | #define AARP_PA_ALEN 4 | 151 | #define AARP_PA_ALEN 4 |
| 152 | __u16 function; | 152 | __be16 function; |
| 153 | #define AARP_REQUEST 1 | 153 | #define AARP_REQUEST 1 |
| 154 | #define AARP_REPLY 2 | 154 | #define AARP_REPLY 2 |
| 155 | #define AARP_PROBE 3 | 155 | #define AARP_PROBE 3 |
| 156 | __u8 hw_src[ETH_ALEN] __attribute__ ((packed)); | 156 | __u8 hw_src[ETH_ALEN] __attribute__ ((packed)); |
| 157 | __u8 pa_src_zero __attribute__ ((packed)); | 157 | __u8 pa_src_zero __attribute__ ((packed)); |
| 158 | __u16 pa_src_net __attribute__ ((packed)); | 158 | __be16 pa_src_net __attribute__ ((packed)); |
| 159 | __u8 pa_src_node __attribute__ ((packed)); | 159 | __u8 pa_src_node __attribute__ ((packed)); |
| 160 | __u8 hw_dst[ETH_ALEN] __attribute__ ((packed)); | 160 | __u8 hw_dst[ETH_ALEN] __attribute__ ((packed)); |
| 161 | __u8 pa_dst_zero __attribute__ ((packed)); | 161 | __u8 pa_dst_zero __attribute__ ((packed)); |
| 162 | __u16 pa_dst_net __attribute__ ((packed)); | 162 | __be16 pa_dst_net __attribute__ ((packed)); |
| 163 | __u8 pa_dst_node __attribute__ ((packed)); | 163 | __u8 pa_dst_node __attribute__ ((packed)); |
| 164 | }; | 164 | }; |
| 165 | 165 | ||
diff --git a/include/linux/netlink.h b/include/linux/netlink.h index e38407a23d04..561d4dc75836 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #define NETLINK_SELINUX 7 /* SELinux event notifications */ | 14 | #define NETLINK_SELINUX 7 /* SELinux event notifications */ |
| 15 | #define NETLINK_ARPD 8 | 15 | #define NETLINK_ARPD 8 |
| 16 | #define NETLINK_AUDIT 9 /* auditing */ | 16 | #define NETLINK_AUDIT 9 /* auditing */ |
| 17 | #define NETLINK_FIB_LOOKUP 10 | ||
| 17 | #define NETLINK_ROUTE6 11 /* af_inet6 route comm channel */ | 18 | #define NETLINK_ROUTE6 11 /* af_inet6 route comm channel */ |
| 18 | #define NETLINK_IP6_FW 13 | 19 | #define NETLINK_IP6_FW 13 |
| 19 | #define NETLINK_DNRTMSG 14 /* DECnet routing messages */ | 20 | #define NETLINK_DNRTMSG 14 /* DECnet routing messages */ |
diff --git a/include/linux/pfkeyv2.h b/include/linux/pfkeyv2.h index e6b519220245..724066778aff 100644 --- a/include/linux/pfkeyv2.h +++ b/include/linux/pfkeyv2.h | |||
| @@ -245,6 +245,7 @@ struct sadb_x_nat_t_port { | |||
| 245 | 245 | ||
| 246 | /* Security Association flags */ | 246 | /* Security Association flags */ |
| 247 | #define SADB_SAFLAGS_PFS 1 | 247 | #define SADB_SAFLAGS_PFS 1 |
| 248 | #define SADB_SAFLAGS_NOPMTUDISC 0x20000000 | ||
| 248 | #define SADB_SAFLAGS_DECAP_DSCP 0x40000000 | 249 | #define SADB_SAFLAGS_DECAP_DSCP 0x40000000 |
| 249 | #define SADB_SAFLAGS_NOECN 0x80000000 | 250 | #define SADB_SAFLAGS_NOECN 0x80000000 |
| 250 | 251 | ||
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index d68391a9b9f3..f0d423300d84 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h | |||
| @@ -196,6 +196,7 @@ struct xfrm_usersa_info { | |||
| 196 | __u8 flags; | 196 | __u8 flags; |
| 197 | #define XFRM_STATE_NOECN 1 | 197 | #define XFRM_STATE_NOECN 1 |
| 198 | #define XFRM_STATE_DECAP_DSCP 2 | 198 | #define XFRM_STATE_DECAP_DSCP 2 |
| 199 | #define XFRM_STATE_NOPMTUDISC 4 | ||
| 199 | }; | 200 | }; |
| 200 | 201 | ||
| 201 | struct xfrm_usersa_id { | 202 | struct xfrm_usersa_id { |
diff --git a/include/net/ax25.h b/include/net/ax25.h index 9e6368a54547..828a3a93dda1 100644 --- a/include/net/ax25.h +++ b/include/net/ax25.h | |||
| @@ -220,7 +220,7 @@ static __inline__ void ax25_cb_put(ax25_cb *ax25) | |||
| 220 | } | 220 | } |
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | static inline unsigned short ax25_type_trans(struct sk_buff *skb, struct net_device *dev) | 223 | static inline __be16 ax25_type_trans(struct sk_buff *skb, struct net_device *dev) |
| 224 | { | 224 | { |
| 225 | skb->dev = dev; | 225 | skb->dev = dev; |
| 226 | skb->pkt_type = PACKET_HOST; | 226 | skb->pkt_type = PACKET_HOST; |
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index e5a5f6b62f88..a4208a336ac0 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h | |||
| @@ -109,6 +109,20 @@ struct fib_result { | |||
| 109 | #endif | 109 | #endif |
| 110 | }; | 110 | }; |
| 111 | 111 | ||
| 112 | struct fib_result_nl { | ||
| 113 | u32 fl_addr; /* To be looked up*/ | ||
| 114 | u32 fl_fwmark; | ||
| 115 | unsigned char fl_tos; | ||
| 116 | unsigned char fl_scope; | ||
| 117 | unsigned char tb_id_in; | ||
| 118 | |||
| 119 | unsigned char tb_id; /* Results */ | ||
| 120 | unsigned char prefixlen; | ||
| 121 | unsigned char nh_sel; | ||
| 122 | unsigned char type; | ||
| 123 | unsigned char scope; | ||
| 124 | int err; | ||
| 125 | }; | ||
| 112 | 126 | ||
| 113 | #ifdef CONFIG_IP_ROUTE_MULTIPATH | 127 | #ifdef CONFIG_IP_ROUTE_MULTIPATH |
| 114 | 128 | ||
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h index ebc5282e6d58..dc107ffad483 100644 --- a/include/net/sctp/command.h +++ b/include/net/sctp/command.h | |||
| @@ -65,9 +65,11 @@ typedef enum { | |||
| 65 | SCTP_CMD_TIMER_START, /* Start a timer. */ | 65 | SCTP_CMD_TIMER_START, /* Start a timer. */ |
| 66 | SCTP_CMD_TIMER_RESTART, /* Restart a timer. */ | 66 | SCTP_CMD_TIMER_RESTART, /* Restart a timer. */ |
| 67 | SCTP_CMD_TIMER_STOP, /* Stop a timer. */ | 67 | SCTP_CMD_TIMER_STOP, /* Stop a timer. */ |
| 68 | SCTP_CMD_COUNTER_RESET, /* Reset a counter. */ | 68 | SCTP_CMD_INIT_CHOOSE_TRANSPORT, /* Choose transport for an INIT. */ |
| 69 | SCTP_CMD_COUNTER_INC, /* Increment a counter. */ | 69 | SCTP_CMD_INIT_COUNTER_RESET, /* Reset init counter. */ |
| 70 | SCTP_CMD_INIT_COUNTER_INC, /* Increment init counter. */ | ||
| 70 | SCTP_CMD_INIT_RESTART, /* High level, do init timer work. */ | 71 | SCTP_CMD_INIT_RESTART, /* High level, do init timer work. */ |
| 72 | SCTP_CMD_COOKIEECHO_RESTART, /* High level, do cookie-echo timer work. */ | ||
| 71 | SCTP_CMD_INIT_FAILED, /* High level, do init failure work. */ | 73 | SCTP_CMD_INIT_FAILED, /* High level, do init failure work. */ |
| 72 | SCTP_CMD_REPORT_DUP, /* Report a duplicate TSN. */ | 74 | SCTP_CMD_REPORT_DUP, /* Report a duplicate TSN. */ |
| 73 | SCTP_CMD_STRIKE, /* Mark a strike against a transport. */ | 75 | SCTP_CMD_STRIKE, /* Mark a strike against a transport. */ |
| @@ -118,7 +120,6 @@ typedef union { | |||
| 118 | int error; | 120 | int error; |
| 119 | sctp_state_t state; | 121 | sctp_state_t state; |
| 120 | sctp_event_timeout_t to; | 122 | sctp_event_timeout_t to; |
| 121 | sctp_counter_t counter; | ||
| 122 | void *ptr; | 123 | void *ptr; |
| 123 | struct sctp_chunk *chunk; | 124 | struct sctp_chunk *chunk; |
| 124 | struct sctp_association *asoc; | 125 | struct sctp_association *asoc; |
| @@ -165,7 +166,6 @@ SCTP_ARG_CONSTRUCTOR(U16, __u16, u16) | |||
| 165 | SCTP_ARG_CONSTRUCTOR(U8, __u8, u8) | 166 | SCTP_ARG_CONSTRUCTOR(U8, __u8, u8) |
| 166 | SCTP_ARG_CONSTRUCTOR(ERROR, int, error) | 167 | SCTP_ARG_CONSTRUCTOR(ERROR, int, error) |
| 167 | SCTP_ARG_CONSTRUCTOR(STATE, sctp_state_t, state) | 168 | SCTP_ARG_CONSTRUCTOR(STATE, sctp_state_t, state) |
| 168 | SCTP_ARG_CONSTRUCTOR(COUNTER, sctp_counter_t, counter) | ||
| 169 | SCTP_ARG_CONSTRUCTOR(TO, sctp_event_timeout_t, to) | 169 | SCTP_ARG_CONSTRUCTOR(TO, sctp_event_timeout_t, to) |
| 170 | SCTP_ARG_CONSTRUCTOR(PTR, void *, ptr) | 170 | SCTP_ARG_CONSTRUCTOR(PTR, void *, ptr) |
| 171 | SCTP_ARG_CONSTRUCTOR(CHUNK, struct sctp_chunk *, chunk) | 171 | SCTP_ARG_CONSTRUCTOR(CHUNK, struct sctp_chunk *, chunk) |
diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h index 2b76c0f4babc..4868c7f7749d 100644 --- a/include/net/sctp/constants.h +++ b/include/net/sctp/constants.h | |||
| @@ -263,13 +263,6 @@ enum { SCTP_MIN_PMTU = 576 }; | |||
| 263 | enum { SCTP_MAX_DUP_TSNS = 16 }; | 263 | enum { SCTP_MAX_DUP_TSNS = 16 }; |
| 264 | enum { SCTP_MAX_GABS = 16 }; | 264 | enum { SCTP_MAX_GABS = 16 }; |
| 265 | 265 | ||
| 266 | typedef enum { | ||
| 267 | SCTP_COUNTER_INIT_ERROR, | ||
| 268 | } sctp_counter_t; | ||
| 269 | |||
| 270 | /* How many counters does an association need? */ | ||
| 271 | #define SCTP_NUMBER_COUNTERS 5 | ||
| 272 | |||
| 273 | /* Here we define the default timers. */ | 266 | /* Here we define the default timers. */ |
| 274 | 267 | ||
| 275 | /* cookie timer def = ? seconds */ | 268 | /* cookie timer def = ? seconds */ |
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 960abfa48d68..ef2738159ab3 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h | |||
| @@ -223,6 +223,22 @@ DECLARE_SNMP_STAT(struct sctp_mib, sctp_statistics); | |||
| 223 | extern int sctp_debug_flag; | 223 | extern int sctp_debug_flag; |
| 224 | #define SCTP_DEBUG_PRINTK(whatever...) \ | 224 | #define SCTP_DEBUG_PRINTK(whatever...) \ |
| 225 | ((void) (sctp_debug_flag && printk(KERN_DEBUG whatever))) | 225 | ((void) (sctp_debug_flag && printk(KERN_DEBUG whatever))) |
| 226 | #define SCTP_DEBUG_PRINTK_IPADDR(lead, trail, leadparm, saddr, otherparms...) \ | ||
| 227 | if (sctp_debug_flag) { \ | ||
| 228 | if (saddr->sa.sa_family == AF_INET6) { \ | ||
| 229 | printk(KERN_DEBUG \ | ||
| 230 | lead "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" trail, \ | ||
| 231 | leadparm, \ | ||
| 232 | NIP6(saddr->v6.sin6_addr), \ | ||
| 233 | otherparms); \ | ||
| 234 | } else { \ | ||
| 235 | printk(KERN_DEBUG \ | ||
| 236 | lead "%u.%u.%u.%u" trail, \ | ||
| 237 | leadparm, \ | ||
| 238 | NIPQUAD(saddr->v4.sin_addr.s_addr), \ | ||
| 239 | otherparms); \ | ||
| 240 | } \ | ||
| 241 | } | ||
| 226 | #define SCTP_ENABLE_DEBUG { sctp_debug_flag = 1; } | 242 | #define SCTP_ENABLE_DEBUG { sctp_debug_flag = 1; } |
| 227 | #define SCTP_DISABLE_DEBUG { sctp_debug_flag = 0; } | 243 | #define SCTP_DISABLE_DEBUG { sctp_debug_flag = 0; } |
| 228 | 244 | ||
| @@ -236,6 +252,7 @@ extern int sctp_debug_flag; | |||
| 236 | #else /* SCTP_DEBUG */ | 252 | #else /* SCTP_DEBUG */ |
| 237 | 253 | ||
| 238 | #define SCTP_DEBUG_PRINTK(whatever...) | 254 | #define SCTP_DEBUG_PRINTK(whatever...) |
| 255 | #define SCTP_DEBUG_PRINTK_IPADDR(whatever...) | ||
| 239 | #define SCTP_ENABLE_DEBUG | 256 | #define SCTP_ENABLE_DEBUG |
| 240 | #define SCTP_DISABLE_DEBUG | 257 | #define SCTP_DISABLE_DEBUG |
| 241 | #define SCTP_ASSERT(expr, str, func) | 258 | #define SCTP_ASSERT(expr, str, func) |
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index f4fcee104707..a53e08a45e32 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h | |||
| @@ -116,7 +116,8 @@ sctp_state_fn_t sctp_sf_eat_data_fast_4_4; | |||
| 116 | sctp_state_fn_t sctp_sf_eat_sack_6_2; | 116 | sctp_state_fn_t sctp_sf_eat_sack_6_2; |
| 117 | sctp_state_fn_t sctp_sf_tabort_8_4_8; | 117 | sctp_state_fn_t sctp_sf_tabort_8_4_8; |
| 118 | sctp_state_fn_t sctp_sf_operr_notify; | 118 | sctp_state_fn_t sctp_sf_operr_notify; |
| 119 | sctp_state_fn_t sctp_sf_t1_timer_expire; | 119 | sctp_state_fn_t sctp_sf_t1_init_timer_expire; |
| 120 | sctp_state_fn_t sctp_sf_t1_cookie_timer_expire; | ||
| 120 | sctp_state_fn_t sctp_sf_t2_timer_expire; | 121 | sctp_state_fn_t sctp_sf_t2_timer_expire; |
| 121 | sctp_state_fn_t sctp_sf_t4_timer_expire; | 122 | sctp_state_fn_t sctp_sf_t4_timer_expire; |
| 122 | sctp_state_fn_t sctp_sf_t5_timer_expire; | 123 | sctp_state_fn_t sctp_sf_t5_timer_expire; |
| @@ -258,7 +259,10 @@ struct sctp_chunk *sctp_make_fwdtsn(const struct sctp_association *asoc, | |||
| 258 | void sctp_chunk_assign_tsn(struct sctp_chunk *); | 259 | void sctp_chunk_assign_tsn(struct sctp_chunk *); |
| 259 | void sctp_chunk_assign_ssn(struct sctp_chunk *); | 260 | void sctp_chunk_assign_ssn(struct sctp_chunk *); |
| 260 | 261 | ||
| 261 | void sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, __u16 error); | 262 | sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, |
| 263 | __u16 error, | ||
| 264 | const struct sctp_association *asoc, | ||
| 265 | struct sctp_transport *transport); | ||
| 262 | 266 | ||
| 263 | /* Prototypes for statetable processing. */ | 267 | /* Prototypes for statetable processing. */ |
| 264 | 268 | ||
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 6c24d9cd3d66..dfad4d3c581c 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h | |||
| @@ -867,10 +867,13 @@ struct sctp_transport { | |||
| 867 | */ | 867 | */ |
| 868 | unsigned long last_time_ecne_reduced; | 868 | unsigned long last_time_ecne_reduced; |
| 869 | 869 | ||
| 870 | /* active : The current active state of this destination, | 870 | /* The number of times INIT has been sent on this transport. */ |
| 871 | * : i.e. DOWN, UP, etc. | 871 | int init_sent_count; |
| 872 | |||
| 873 | /* state : The current state of this destination, | ||
| 874 | * : i.e. SCTP_ACTIVE, SCTP_INACTIVE, SCTP_UNKOWN. | ||
| 872 | */ | 875 | */ |
| 873 | int active; | 876 | int state; |
| 874 | 877 | ||
| 875 | /* hb_allowed : The current heartbeat state of this destination, | 878 | /* hb_allowed : The current heartbeat state of this destination, |
| 876 | * : i.e. ALLOW-HB, NO-HEARTBEAT, etc. | 879 | * : i.e. ALLOW-HB, NO-HEARTBEAT, etc. |
| @@ -1222,9 +1225,6 @@ struct sctp_endpoint { | |||
| 1222 | 1225 | ||
| 1223 | /* sendbuf acct. policy. */ | 1226 | /* sendbuf acct. policy. */ |
| 1224 | __u32 sndbuf_policy; | 1227 | __u32 sndbuf_policy; |
| 1225 | |||
| 1226 | /* Name for debugging output... */ | ||
| 1227 | char *debug_name; | ||
| 1228 | }; | 1228 | }; |
| 1229 | 1229 | ||
| 1230 | /* Recover the outter endpoint structure. */ | 1230 | /* Recover the outter endpoint structure. */ |
| @@ -1314,11 +1314,23 @@ struct sctp_association { | |||
| 1314 | * : association. Normally this information is | 1314 | * : association. Normally this information is |
| 1315 | * : hashed or keyed for quick lookup and access | 1315 | * : hashed or keyed for quick lookup and access |
| 1316 | * : of the TCB. | 1316 | * : of the TCB. |
| 1317 | * : The list is also initialized with the list | ||
| 1318 | * : of addresses passed with the sctp_connectx() | ||
| 1319 | * : call. | ||
| 1317 | * | 1320 | * |
| 1318 | * It is a list of SCTP_transport's. | 1321 | * It is a list of SCTP_transport's. |
| 1319 | */ | 1322 | */ |
| 1320 | struct list_head transport_addr_list; | 1323 | struct list_head transport_addr_list; |
| 1321 | 1324 | ||
| 1325 | /* transport_count | ||
| 1326 | * | ||
| 1327 | * Peer : A count of the number of peer addresses | ||
| 1328 | * Transport : in the Peer Transport Address List. | ||
| 1329 | * Address : | ||
| 1330 | * Count : | ||
| 1331 | */ | ||
| 1332 | __u16 transport_count; | ||
| 1333 | |||
| 1322 | /* port | 1334 | /* port |
| 1323 | * The transport layer port number. | 1335 | * The transport layer port number. |
| 1324 | */ | 1336 | */ |
| @@ -1486,6 +1498,9 @@ struct sctp_association { | |||
| 1486 | /* Transport to which SHUTDOWN chunk was last sent. */ | 1498 | /* Transport to which SHUTDOWN chunk was last sent. */ |
| 1487 | struct sctp_transport *shutdown_last_sent_to; | 1499 | struct sctp_transport *shutdown_last_sent_to; |
| 1488 | 1500 | ||
| 1501 | /* Transport to which INIT chunk was last sent. */ | ||
| 1502 | struct sctp_transport *init_last_sent_to; | ||
| 1503 | |||
| 1489 | /* Next TSN : The next TSN number to be assigned to a new | 1504 | /* Next TSN : The next TSN number to be assigned to a new |
| 1490 | * : DATA chunk. This is sent in the INIT or INIT | 1505 | * : DATA chunk. This is sent in the INIT or INIT |
| 1491 | * : ACK chunk to the peer and incremented each | 1506 | * : ACK chunk to the peer and incremented each |
| @@ -1549,8 +1564,11 @@ struct sctp_association { | |||
| 1549 | /* The message size at which SCTP fragmentation will occur. */ | 1564 | /* The message size at which SCTP fragmentation will occur. */ |
| 1550 | __u32 frag_point; | 1565 | __u32 frag_point; |
| 1551 | 1566 | ||
| 1552 | /* Currently only one counter is used to count INIT errors. */ | 1567 | /* Counter used to count INIT errors. */ |
| 1553 | int counters[SCTP_NUMBER_COUNTERS]; | 1568 | int init_err_counter; |
| 1569 | |||
| 1570 | /* Count the number of INIT cycles (for doubling timeout). */ | ||
| 1571 | int init_cycle; | ||
| 1554 | 1572 | ||
| 1555 | /* Default send parameters. */ | 1573 | /* Default send parameters. */ |
| 1556 | __u16 default_stream; | 1574 | __u16 default_stream; |
| @@ -1708,6 +1726,8 @@ void sctp_association_free(struct sctp_association *); | |||
| 1708 | void sctp_association_put(struct sctp_association *); | 1726 | void sctp_association_put(struct sctp_association *); |
| 1709 | void sctp_association_hold(struct sctp_association *); | 1727 | void sctp_association_hold(struct sctp_association *); |
| 1710 | 1728 | ||
| 1729 | struct sctp_transport *sctp_assoc_choose_init_transport( | ||
| 1730 | struct sctp_association *); | ||
| 1711 | struct sctp_transport *sctp_assoc_choose_shutdown_transport( | 1731 | struct sctp_transport *sctp_assoc_choose_shutdown_transport( |
| 1712 | struct sctp_association *); | 1732 | struct sctp_association *); |
| 1713 | void sctp_assoc_update_retran_path(struct sctp_association *); | 1733 | void sctp_assoc_update_retran_path(struct sctp_association *); |
| @@ -1717,9 +1737,12 @@ int sctp_assoc_lookup_laddr(struct sctp_association *asoc, | |||
| 1717 | const union sctp_addr *laddr); | 1737 | const union sctp_addr *laddr); |
| 1718 | struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *, | 1738 | struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *, |
| 1719 | const union sctp_addr *address, | 1739 | const union sctp_addr *address, |
| 1720 | const int gfp); | 1740 | const int gfp, |
| 1741 | const int peer_state); | ||
| 1721 | void sctp_assoc_del_peer(struct sctp_association *asoc, | 1742 | void sctp_assoc_del_peer(struct sctp_association *asoc, |
| 1722 | const union sctp_addr *addr); | 1743 | const union sctp_addr *addr); |
| 1744 | void sctp_assoc_rm_peer(struct sctp_association *asoc, | ||
| 1745 | struct sctp_transport *peer); | ||
| 1723 | void sctp_assoc_control_transport(struct sctp_association *, | 1746 | void sctp_assoc_control_transport(struct sctp_association *, |
| 1724 | struct sctp_transport *, | 1747 | struct sctp_transport *, |
| 1725 | sctp_transport_cmd_t, sctp_sn_error_t); | 1748 | sctp_transport_cmd_t, sctp_sn_error_t); |
diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h index 2758e8ce4f25..f6328aeddcce 100644 --- a/include/net/sctp/user.h +++ b/include/net/sctp/user.h | |||
| @@ -111,6 +111,8 @@ enum sctp_optname { | |||
| 111 | #define SCTP_GET_LOCAL_ADDRS_NUM SCTP_GET_LOCAL_ADDRS_NUM | 111 | #define SCTP_GET_LOCAL_ADDRS_NUM SCTP_GET_LOCAL_ADDRS_NUM |
| 112 | SCTP_GET_LOCAL_ADDRS, /* Get all local addresss. */ | 112 | SCTP_GET_LOCAL_ADDRS, /* Get all local addresss. */ |
| 113 | #define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS | 113 | #define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS |
| 114 | SCTP_SOCKOPT_CONNECTX, /* CONNECTX requests. */ | ||
| 115 | #define SCTP_SOCKOPT_CONNECTX SCTP_SOCKOPT_CONNECTX | ||
| 114 | }; | 116 | }; |
| 115 | 117 | ||
| 116 | /* | 118 | /* |
| @@ -527,6 +529,7 @@ struct sctp_paddrinfo { | |||
| 527 | enum sctp_spinfo_state { | 529 | enum sctp_spinfo_state { |
| 528 | SCTP_INACTIVE, | 530 | SCTP_INACTIVE, |
| 529 | SCTP_ACTIVE, | 531 | SCTP_ACTIVE, |
| 532 | SCTP_UNKNOWN = 0xffff /* Value used for transport state unknown */ | ||
| 530 | }; | 533 | }; |
| 531 | 534 | ||
| 532 | /* | 535 | /* |
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 0e65e02b7a1d..029522a4ceda 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
| @@ -204,6 +204,7 @@ struct xfrm_state_afinfo { | |||
| 204 | rwlock_t lock; | 204 | rwlock_t lock; |
| 205 | struct list_head *state_bydst; | 205 | struct list_head *state_bydst; |
| 206 | struct list_head *state_byspi; | 206 | struct list_head *state_byspi; |
| 207 | int (*init_flags)(struct xfrm_state *x); | ||
| 207 | void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl, | 208 | void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl, |
| 208 | struct xfrm_tmpl *tmpl, | 209 | struct xfrm_tmpl *tmpl, |
| 209 | xfrm_address_t *daddr, xfrm_address_t *saddr); | 210 | xfrm_address_t *daddr, xfrm_address_t *saddr); |
| @@ -225,7 +226,7 @@ struct xfrm_type | |||
| 225 | struct module *owner; | 226 | struct module *owner; |
| 226 | __u8 proto; | 227 | __u8 proto; |
| 227 | 228 | ||
| 228 | int (*init_state)(struct xfrm_state *x, void *args); | 229 | int (*init_state)(struct xfrm_state *x); |
| 229 | void (*destructor)(struct xfrm_state *); | 230 | void (*destructor)(struct xfrm_state *); |
| 230 | int (*input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb); | 231 | int (*input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb); |
| 231 | int (*post_input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb); | 232 | int (*post_input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb); |
| @@ -839,6 +840,7 @@ extern int xfrm_replay_check(struct xfrm_state *x, u32 seq); | |||
| 839 | extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq); | 840 | extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq); |
| 840 | extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb); | 841 | extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb); |
| 841 | extern int xfrm_state_mtu(struct xfrm_state *x, int mtu); | 842 | extern int xfrm_state_mtu(struct xfrm_state *x, int mtu); |
| 843 | extern int xfrm_init_state(struct xfrm_state *x); | ||
| 842 | extern int xfrm4_rcv(struct sk_buff *skb); | 844 | extern int xfrm4_rcv(struct sk_buff *skb); |
| 843 | extern int xfrm4_output(struct sk_buff *skb); | 845 | extern int xfrm4_output(struct sk_buff *skb); |
| 844 | extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler); | 846 | extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler); |
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c index 54640c01b50c..10d040461021 100644 --- a/net/appletalk/aarp.c +++ b/net/appletalk/aarp.c | |||
| @@ -565,7 +565,7 @@ int aarp_send_ddp(struct net_device *dev, struct sk_buff *skb, | |||
| 565 | * numbers we just happen to need. Now put the | 565 | * numbers we just happen to need. Now put the |
| 566 | * length in the lower two. | 566 | * length in the lower two. |
| 567 | */ | 567 | */ |
| 568 | *((__u16 *)skb->data) = htons(skb->len); | 568 | *((__be16 *)skb->data) = htons(skb->len); |
| 569 | ft = 1; | 569 | ft = 1; |
| 570 | } | 570 | } |
| 571 | /* | 571 | /* |
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 876dbac71060..192b529f86a4 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c | |||
| @@ -401,7 +401,7 @@ out_err: | |||
| 401 | } | 401 | } |
| 402 | 402 | ||
| 403 | /* Find a match for a specific network:node pair */ | 403 | /* Find a match for a specific network:node pair */ |
| 404 | static struct atalk_iface *atalk_find_interface(int net, int node) | 404 | static struct atalk_iface *atalk_find_interface(__be16 net, int node) |
| 405 | { | 405 | { |
| 406 | struct atalk_iface *iface; | 406 | struct atalk_iface *iface; |
| 407 | 407 | ||
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index 0e98f2235b6e..514c85b2631a 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c | |||
| @@ -200,7 +200,7 @@ static void ah4_err(struct sk_buff *skb, u32 info) | |||
| 200 | xfrm_state_put(x); | 200 | xfrm_state_put(x); |
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | static int ah_init_state(struct xfrm_state *x, void *args) | 203 | static int ah_init_state(struct xfrm_state *x) |
| 204 | { | 204 | { |
| 205 | struct ah_data *ahp = NULL; | 205 | struct ah_data *ahp = NULL; |
| 206 | struct xfrm_algo_desc *aalg_desc; | 206 | struct xfrm_algo_desc *aalg_desc; |
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index eae84cc39d3f..ba57446d5d1f 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c | |||
| @@ -362,7 +362,7 @@ static void esp_destroy(struct xfrm_state *x) | |||
| 362 | kfree(esp); | 362 | kfree(esp); |
| 363 | } | 363 | } |
| 364 | 364 | ||
| 365 | static int esp_init_state(struct xfrm_state *x, void *args) | 365 | static int esp_init_state(struct xfrm_state *x) |
| 366 | { | 366 | { |
| 367 | struct esp_data *esp = NULL; | 367 | struct esp_data *esp = NULL; |
| 368 | 368 | ||
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 563e7d612706..cd8e45ab9580 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
| @@ -516,6 +516,60 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa) | |||
| 516 | #undef BRD1_OK | 516 | #undef BRD1_OK |
| 517 | } | 517 | } |
| 518 | 518 | ||
| 519 | static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb ) | ||
| 520 | { | ||
| 521 | |||
| 522 | struct fib_result res; | ||
| 523 | struct flowi fl = { .nl_u = { .ip4_u = { .daddr = frn->fl_addr, | ||
| 524 | .fwmark = frn->fl_fwmark, | ||
| 525 | .tos = frn->fl_tos, | ||
| 526 | .scope = frn->fl_scope } } }; | ||
| 527 | if (tb) { | ||
| 528 | local_bh_disable(); | ||
| 529 | |||
| 530 | frn->tb_id = tb->tb_id; | ||
| 531 | frn->err = tb->tb_lookup(tb, &fl, &res); | ||
| 532 | |||
| 533 | if (!frn->err) { | ||
| 534 | frn->prefixlen = res.prefixlen; | ||
| 535 | frn->nh_sel = res.nh_sel; | ||
| 536 | frn->type = res.type; | ||
| 537 | frn->scope = res.scope; | ||
| 538 | } | ||
| 539 | local_bh_enable(); | ||
| 540 | } | ||
| 541 | } | ||
| 542 | |||
| 543 | static void nl_fib_input(struct sock *sk, int len) | ||
| 544 | { | ||
| 545 | struct sk_buff *skb = NULL; | ||
| 546 | struct nlmsghdr *nlh = NULL; | ||
| 547 | struct fib_result_nl *frn; | ||
| 548 | int err; | ||
| 549 | u32 pid; | ||
| 550 | struct fib_table *tb; | ||
| 551 | |||
| 552 | skb = skb_recv_datagram(sk, 0, 0, &err); | ||
| 553 | nlh = (struct nlmsghdr *)skb->data; | ||
| 554 | |||
| 555 | frn = (struct fib_result_nl *) NLMSG_DATA(nlh); | ||
| 556 | tb = fib_get_table(frn->tb_id_in); | ||
| 557 | |||
| 558 | nl_fib_lookup(frn, tb); | ||
| 559 | |||
| 560 | pid = nlh->nlmsg_pid; /*pid of sending process */ | ||
| 561 | NETLINK_CB(skb).groups = 0; /* not in mcast group */ | ||
| 562 | NETLINK_CB(skb).pid = 0; /* from kernel */ | ||
| 563 | NETLINK_CB(skb).dst_pid = pid; | ||
| 564 | NETLINK_CB(skb).dst_groups = 0; /* unicast */ | ||
| 565 | netlink_unicast(sk, skb, pid, MSG_DONTWAIT); | ||
| 566 | } | ||
| 567 | |||
| 568 | static void nl_fib_lookup_init(void) | ||
| 569 | { | ||
| 570 | netlink_kernel_create(NETLINK_FIB_LOOKUP, nl_fib_input); | ||
| 571 | } | ||
| 572 | |||
| 519 | static void fib_disable_ip(struct net_device *dev, int force) | 573 | static void fib_disable_ip(struct net_device *dev, int force) |
| 520 | { | 574 | { |
| 521 | if (fib_sync_down(0, dev, force)) | 575 | if (fib_sync_down(0, dev, force)) |
| @@ -604,6 +658,7 @@ void __init ip_fib_init(void) | |||
| 604 | 658 | ||
| 605 | register_netdevice_notifier(&fib_netdev_notifier); | 659 | register_netdevice_notifier(&fib_netdev_notifier); |
| 606 | register_inetaddr_notifier(&fib_inetaddr_notifier); | 660 | register_inetaddr_notifier(&fib_inetaddr_notifier); |
| 661 | nl_fib_lookup_init(); | ||
| 607 | } | 662 | } |
| 608 | 663 | ||
| 609 | EXPORT_SYMBOL(inet_addr_type); | 664 | EXPORT_SYMBOL(inet_addr_type); |
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index 1a23c5263b99..2065944fd9e5 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c | |||
| @@ -236,15 +236,10 @@ static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x) | |||
| 236 | t->props.mode = 1; | 236 | t->props.mode = 1; |
| 237 | t->props.saddr.a4 = x->props.saddr.a4; | 237 | t->props.saddr.a4 = x->props.saddr.a4; |
| 238 | t->props.flags = x->props.flags; | 238 | t->props.flags = x->props.flags; |
| 239 | 239 | ||
| 240 | t->type = xfrm_get_type(IPPROTO_IPIP, t->props.family); | 240 | if (xfrm_init_state(t)) |
| 241 | if (t->type == NULL) | ||
| 242 | goto error; | ||
| 243 | |||
| 244 | if (t->type->init_state(t, NULL)) | ||
| 245 | goto error; | 241 | goto error; |
| 246 | 242 | ||
| 247 | t->km.state = XFRM_STATE_VALID; | ||
| 248 | atomic_set(&t->tunnel_users, 1); | 243 | atomic_set(&t->tunnel_users, 1); |
| 249 | out: | 244 | out: |
| 250 | return t; | 245 | return t; |
| @@ -422,7 +417,7 @@ static void ipcomp_destroy(struct xfrm_state *x) | |||
| 422 | kfree(ipcd); | 417 | kfree(ipcd); |
| 423 | } | 418 | } |
| 424 | 419 | ||
| 425 | static int ipcomp_init_state(struct xfrm_state *x, void *args) | 420 | static int ipcomp_init_state(struct xfrm_state *x) |
| 426 | { | 421 | { |
| 427 | int err; | 422 | int err; |
| 428 | struct ipcomp_data *ipcd; | 423 | struct ipcomp_data *ipcd; |
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index af2392ae5769..66620a95942a 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c | |||
| @@ -33,6 +33,7 @@ static void xfrm4_encap(struct sk_buff *skb) | |||
| 33 | struct dst_entry *dst = skb->dst; | 33 | struct dst_entry *dst = skb->dst; |
| 34 | struct xfrm_state *x = dst->xfrm; | 34 | struct xfrm_state *x = dst->xfrm; |
| 35 | struct iphdr *iph, *top_iph; | 35 | struct iphdr *iph, *top_iph; |
| 36 | int flags; | ||
| 36 | 37 | ||
| 37 | iph = skb->nh.iph; | 38 | iph = skb->nh.iph; |
| 38 | skb->h.ipiph = iph; | 39 | skb->h.ipiph = iph; |
| @@ -51,10 +52,13 @@ static void xfrm4_encap(struct sk_buff *skb) | |||
| 51 | 52 | ||
| 52 | /* DS disclosed */ | 53 | /* DS disclosed */ |
| 53 | top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos); | 54 | top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos); |
| 54 | if (x->props.flags & XFRM_STATE_NOECN) | 55 | |
| 56 | flags = x->props.flags; | ||
| 57 | if (flags & XFRM_STATE_NOECN) | ||
| 55 | IP_ECN_clear(top_iph); | 58 | IP_ECN_clear(top_iph); |
| 56 | 59 | ||
| 57 | top_iph->frag_off = iph->frag_off & htons(IP_DF); | 60 | top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ? |
| 61 | 0 : (iph->frag_off & htons(IP_DF)); | ||
| 58 | if (!top_iph->frag_off) | 62 | if (!top_iph->frag_off) |
| 59 | __ip_select_ident(top_iph, dst, 0); | 63 | __ip_select_ident(top_iph, dst, 0); |
| 60 | 64 | ||
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index 223a2e83853f..050611d7a967 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c | |||
| @@ -7,12 +7,20 @@ | |||
| 7 | * | 7 | * |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | #include <net/ip.h> | ||
| 10 | #include <net/xfrm.h> | 11 | #include <net/xfrm.h> |
| 11 | #include <linux/pfkeyv2.h> | 12 | #include <linux/pfkeyv2.h> |
| 12 | #include <linux/ipsec.h> | 13 | #include <linux/ipsec.h> |
| 13 | 14 | ||
| 14 | static struct xfrm_state_afinfo xfrm4_state_afinfo; | 15 | static struct xfrm_state_afinfo xfrm4_state_afinfo; |
| 15 | 16 | ||
| 17 | static int xfrm4_init_flags(struct xfrm_state *x) | ||
| 18 | { | ||
| 19 | if (ipv4_config.no_pmtu_disc) | ||
| 20 | x->props.flags |= XFRM_STATE_NOPMTUDISC; | ||
| 21 | return 0; | ||
| 22 | } | ||
| 23 | |||
| 16 | static void | 24 | static void |
| 17 | __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl, | 25 | __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl, |
| 18 | struct xfrm_tmpl *tmpl, | 26 | struct xfrm_tmpl *tmpl, |
| @@ -109,6 +117,7 @@ __xfrm4_find_acq(u8 mode, u32 reqid, u8 proto, | |||
| 109 | static struct xfrm_state_afinfo xfrm4_state_afinfo = { | 117 | static struct xfrm_state_afinfo xfrm4_state_afinfo = { |
| 110 | .family = AF_INET, | 118 | .family = AF_INET, |
| 111 | .lock = RW_LOCK_UNLOCKED, | 119 | .lock = RW_LOCK_UNLOCKED, |
| 120 | .init_flags = xfrm4_init_flags, | ||
| 112 | .init_tempsel = __xfrm4_init_tempsel, | 121 | .init_tempsel = __xfrm4_init_tempsel, |
| 113 | .state_lookup = __xfrm4_state_lookup, | 122 | .state_lookup = __xfrm4_state_lookup, |
| 114 | .find_acq = __xfrm4_find_acq, | 123 | .find_acq = __xfrm4_find_acq, |
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c index 413191f585f6..e1fe360ed27a 100644 --- a/net/ipv4/xfrm4_tunnel.c +++ b/net/ipv4/xfrm4_tunnel.c | |||
| @@ -84,7 +84,7 @@ static void ipip_err(struct sk_buff *skb, u32 info) | |||
| 84 | handler->err_handler(skb, &arg); | 84 | handler->err_handler(skb, &arg); |
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | static int ipip_init_state(struct xfrm_state *x, void *args) | 87 | static int ipip_init_state(struct xfrm_state *x) |
| 88 | { | 88 | { |
| 89 | if (!x->props.mode) | 89 | if (!x->props.mode) |
| 90 | return -EINVAL; | 90 | return -EINVAL; |
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index e3ecf626cbf7..986fdfdccbcd 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c | |||
| @@ -339,7 +339,7 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
| 339 | xfrm_state_put(x); | 339 | xfrm_state_put(x); |
| 340 | } | 340 | } |
| 341 | 341 | ||
| 342 | static int ah6_init_state(struct xfrm_state *x, void *args) | 342 | static int ah6_init_state(struct xfrm_state *x) |
| 343 | { | 343 | { |
| 344 | struct ah_data *ahp = NULL; | 344 | struct ah_data *ahp = NULL; |
| 345 | struct xfrm_algo_desc *aalg_desc; | 345 | struct xfrm_algo_desc *aalg_desc; |
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index be7095d6babe..324db62515a2 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
| @@ -296,7 +296,7 @@ static void esp6_destroy(struct xfrm_state *x) | |||
| 296 | kfree(esp); | 296 | kfree(esp); |
| 297 | } | 297 | } |
| 298 | 298 | ||
| 299 | static int esp6_init_state(struct xfrm_state *x, void *args) | 299 | static int esp6_init_state(struct xfrm_state *x) |
| 300 | { | 300 | { |
| 301 | struct esp_data *esp = NULL; | 301 | struct esp_data *esp = NULL; |
| 302 | 302 | ||
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 6cde5310cd76..423feb46ccc0 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c | |||
| @@ -234,14 +234,9 @@ static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x) | |||
| 234 | t->props.mode = 1; | 234 | t->props.mode = 1; |
| 235 | memcpy(t->props.saddr.a6, x->props.saddr.a6, sizeof(struct in6_addr)); | 235 | memcpy(t->props.saddr.a6, x->props.saddr.a6, sizeof(struct in6_addr)); |
| 236 | 236 | ||
| 237 | t->type = xfrm_get_type(IPPROTO_IPV6, t->props.family); | 237 | if (xfrm_init_state(t)) |
| 238 | if (t->type == NULL) | ||
| 239 | goto error; | 238 | goto error; |
| 240 | 239 | ||
| 241 | if (t->type->init_state(t, NULL)) | ||
| 242 | goto error; | ||
| 243 | |||
| 244 | t->km.state = XFRM_STATE_VALID; | ||
| 245 | atomic_set(&t->tunnel_users, 1); | 240 | atomic_set(&t->tunnel_users, 1); |
| 246 | 241 | ||
| 247 | out: | 242 | out: |
| @@ -420,7 +415,7 @@ static void ipcomp6_destroy(struct xfrm_state *x) | |||
| 420 | xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr); | 415 | xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr); |
| 421 | } | 416 | } |
| 422 | 417 | ||
| 423 | static int ipcomp6_init_state(struct xfrm_state *x, void *args) | 418 | static int ipcomp6_init_state(struct xfrm_state *x) |
| 424 | { | 419 | { |
| 425 | int err; | 420 | int err; |
| 426 | struct ipcomp_data *ipcd; | 421 | struct ipcomp_data *ipcd; |
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index ffcadd68b951..60c26c87277e 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c | |||
| @@ -466,7 +466,7 @@ static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
| 466 | return; | 466 | return; |
| 467 | } | 467 | } |
| 468 | 468 | ||
| 469 | static int xfrm6_tunnel_init_state(struct xfrm_state *x, void *args) | 469 | static int xfrm6_tunnel_init_state(struct xfrm_state *x) |
| 470 | { | 470 | { |
| 471 | if (!x->props.mode) | 471 | if (!x->props.mode) |
| 472 | return -EINVAL; | 472 | return -EINVAL; |
diff --git a/net/key/af_key.c b/net/key/af_key.c index 98b72f2024ff..4879743b945a 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
| @@ -690,6 +690,8 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, | |||
| 690 | sa->sadb_sa_flags |= SADB_SAFLAGS_NOECN; | 690 | sa->sadb_sa_flags |= SADB_SAFLAGS_NOECN; |
| 691 | if (x->props.flags & XFRM_STATE_DECAP_DSCP) | 691 | if (x->props.flags & XFRM_STATE_DECAP_DSCP) |
| 692 | sa->sadb_sa_flags |= SADB_SAFLAGS_DECAP_DSCP; | 692 | sa->sadb_sa_flags |= SADB_SAFLAGS_DECAP_DSCP; |
| 693 | if (x->props.flags & XFRM_STATE_NOPMTUDISC) | ||
| 694 | sa->sadb_sa_flags |= SADB_SAFLAGS_NOPMTUDISC; | ||
| 693 | 695 | ||
| 694 | /* hard time */ | 696 | /* hard time */ |
| 695 | if (hsc & 2) { | 697 | if (hsc & 2) { |
| @@ -974,6 +976,8 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, | |||
| 974 | x->props.flags |= XFRM_STATE_NOECN; | 976 | x->props.flags |= XFRM_STATE_NOECN; |
| 975 | if (sa->sadb_sa_flags & SADB_SAFLAGS_DECAP_DSCP) | 977 | if (sa->sadb_sa_flags & SADB_SAFLAGS_DECAP_DSCP) |
| 976 | x->props.flags |= XFRM_STATE_DECAP_DSCP; | 978 | x->props.flags |= XFRM_STATE_DECAP_DSCP; |
| 979 | if (sa->sadb_sa_flags & SADB_SAFLAGS_NOPMTUDISC) | ||
| 980 | x->props.flags |= XFRM_STATE_NOPMTUDISC; | ||
| 977 | 981 | ||
| 978 | lifetime = (struct sadb_lifetime*) ext_hdrs[SADB_EXT_LIFETIME_HARD-1]; | 982 | lifetime = (struct sadb_lifetime*) ext_hdrs[SADB_EXT_LIFETIME_HARD-1]; |
| 979 | if (lifetime != NULL) { | 983 | if (lifetime != NULL) { |
| @@ -1096,17 +1100,11 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, | |||
| 1096 | } | 1100 | } |
| 1097 | } | 1101 | } |
| 1098 | 1102 | ||
| 1099 | x->type = xfrm_get_type(proto, x->props.family); | 1103 | err = xfrm_init_state(x); |
| 1100 | if (x->type == NULL) { | 1104 | if (err) |
| 1101 | err = -ENOPROTOOPT; | ||
| 1102 | goto out; | ||
| 1103 | } | ||
| 1104 | if (x->type->init_state(x, NULL)) { | ||
| 1105 | err = -EINVAL; | ||
| 1106 | goto out; | 1105 | goto out; |
| 1107 | } | 1106 | |
| 1108 | x->km.seq = hdr->sadb_msg_seq; | 1107 | x->km.seq = hdr->sadb_msg_seq; |
| 1109 | x->km.state = XFRM_STATE_VALID; | ||
| 1110 | return x; | 1108 | return x; |
| 1111 | 1109 | ||
| 1112 | out: | 1110 | out: |
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 663843d97a92..7ae6aa772dab 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
| @@ -191,10 +191,6 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
| 191 | asoc->last_cwr_tsn = asoc->ctsn_ack_point; | 191 | asoc->last_cwr_tsn = asoc->ctsn_ack_point; |
| 192 | asoc->unack_data = 0; | 192 | asoc->unack_data = 0; |
| 193 | 193 | ||
| 194 | SCTP_DEBUG_PRINTK("myctsnap for %s INIT as 0x%x.\n", | ||
| 195 | asoc->ep->debug_name, | ||
| 196 | asoc->ctsn_ack_point); | ||
| 197 | |||
| 198 | /* ADDIP Section 4.1 Asconf Chunk Procedures | 194 | /* ADDIP Section 4.1 Asconf Chunk Procedures |
| 199 | * | 195 | * |
| 200 | * When an endpoint has an ASCONF signaled change to be sent to the | 196 | * When an endpoint has an ASCONF signaled change to be sent to the |
| @@ -211,6 +207,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
| 211 | 207 | ||
| 212 | /* Make an empty list of remote transport addresses. */ | 208 | /* Make an empty list of remote transport addresses. */ |
| 213 | INIT_LIST_HEAD(&asoc->peer.transport_addr_list); | 209 | INIT_LIST_HEAD(&asoc->peer.transport_addr_list); |
| 210 | asoc->peer.transport_count = 0; | ||
| 214 | 211 | ||
| 215 | /* RFC 2960 5.1 Normal Establishment of an Association | 212 | /* RFC 2960 5.1 Normal Establishment of an Association |
| 216 | * | 213 | * |
| @@ -288,6 +285,7 @@ struct sctp_association *sctp_association_new(const struct sctp_endpoint *ep, | |||
| 288 | 285 | ||
| 289 | asoc->base.malloced = 1; | 286 | asoc->base.malloced = 1; |
| 290 | SCTP_DBG_OBJCNT_INC(assoc); | 287 | SCTP_DBG_OBJCNT_INC(assoc); |
| 288 | SCTP_DEBUG_PRINTK("Created asoc %p\n", asoc); | ||
| 291 | 289 | ||
| 292 | return asoc; | 290 | return asoc; |
| 293 | 291 | ||
| @@ -356,6 +354,8 @@ void sctp_association_free(struct sctp_association *asoc) | |||
| 356 | sctp_transport_free(transport); | 354 | sctp_transport_free(transport); |
| 357 | } | 355 | } |
| 358 | 356 | ||
| 357 | asoc->peer.transport_count = 0; | ||
| 358 | |||
| 359 | /* Free any cached ASCONF_ACK chunk. */ | 359 | /* Free any cached ASCONF_ACK chunk. */ |
| 360 | if (asoc->addip_last_asconf_ack) | 360 | if (asoc->addip_last_asconf_ack) |
| 361 | sctp_chunk_free(asoc->addip_last_asconf_ack); | 361 | sctp_chunk_free(asoc->addip_last_asconf_ack); |
| @@ -400,7 +400,7 @@ void sctp_assoc_set_primary(struct sctp_association *asoc, | |||
| 400 | /* If the primary path is changing, assume that the | 400 | /* If the primary path is changing, assume that the |
| 401 | * user wants to use this new path. | 401 | * user wants to use this new path. |
| 402 | */ | 402 | */ |
| 403 | if (transport->active) | 403 | if (transport->state != SCTP_INACTIVE) |
| 404 | asoc->peer.active_path = transport; | 404 | asoc->peer.active_path = transport; |
| 405 | 405 | ||
| 406 | /* | 406 | /* |
| @@ -428,10 +428,58 @@ void sctp_assoc_set_primary(struct sctp_association *asoc, | |||
| 428 | transport->cacc.next_tsn_at_change = asoc->next_tsn; | 428 | transport->cacc.next_tsn_at_change = asoc->next_tsn; |
| 429 | } | 429 | } |
| 430 | 430 | ||
| 431 | /* Remove a transport from an association. */ | ||
| 432 | void sctp_assoc_rm_peer(struct sctp_association *asoc, | ||
| 433 | struct sctp_transport *peer) | ||
| 434 | { | ||
| 435 | struct list_head *pos; | ||
| 436 | struct sctp_transport *transport; | ||
| 437 | |||
| 438 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_rm_peer:association %p addr: ", | ||
| 439 | " port: %d\n", | ||
| 440 | asoc, | ||
| 441 | (&peer->ipaddr), | ||
| 442 | peer->ipaddr.v4.sin_port); | ||
| 443 | |||
| 444 | /* If we are to remove the current retran_path, update it | ||
| 445 | * to the next peer before removing this peer from the list. | ||
| 446 | */ | ||
| 447 | if (asoc->peer.retran_path == peer) | ||
| 448 | sctp_assoc_update_retran_path(asoc); | ||
| 449 | |||
| 450 | /* Remove this peer from the list. */ | ||
| 451 | list_del(&peer->transports); | ||
| 452 | |||
| 453 | /* Get the first transport of asoc. */ | ||
| 454 | pos = asoc->peer.transport_addr_list.next; | ||
| 455 | transport = list_entry(pos, struct sctp_transport, transports); | ||
| 456 | |||
| 457 | /* Update any entries that match the peer to be deleted. */ | ||
| 458 | if (asoc->peer.primary_path == peer) | ||
| 459 | sctp_assoc_set_primary(asoc, transport); | ||
| 460 | if (asoc->peer.active_path == peer) | ||
| 461 | asoc->peer.active_path = transport; | ||
| 462 | if (asoc->peer.last_data_from == peer) | ||
| 463 | asoc->peer.last_data_from = transport; | ||
| 464 | |||
| 465 | /* If we remove the transport an INIT was last sent to, set it to | ||
| 466 | * NULL. Combined with the update of the retran path above, this | ||
| 467 | * will cause the next INIT to be sent to the next available | ||
| 468 | * transport, maintaining the cycle. | ||
| 469 | */ | ||
| 470 | if (asoc->init_last_sent_to == peer) | ||
| 471 | asoc->init_last_sent_to = NULL; | ||
| 472 | |||
| 473 | asoc->peer.transport_count--; | ||
| 474 | |||
| 475 | sctp_transport_free(peer); | ||
| 476 | } | ||
| 477 | |||
| 431 | /* Add a transport address to an association. */ | 478 | /* Add a transport address to an association. */ |
| 432 | struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | 479 | struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, |
| 433 | const union sctp_addr *addr, | 480 | const union sctp_addr *addr, |
| 434 | int gfp) | 481 | const int gfp, |
| 482 | const int peer_state) | ||
| 435 | { | 483 | { |
| 436 | struct sctp_transport *peer; | 484 | struct sctp_transport *peer; |
| 437 | struct sctp_sock *sp; | 485 | struct sctp_sock *sp; |
| @@ -442,14 +490,25 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
| 442 | /* AF_INET and AF_INET6 share common port field. */ | 490 | /* AF_INET and AF_INET6 share common port field. */ |
| 443 | port = addr->v4.sin_port; | 491 | port = addr->v4.sin_port; |
| 444 | 492 | ||
| 493 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_add_peer:association %p addr: ", | ||
| 494 | " port: %d state:%s\n", | ||
| 495 | asoc, | ||
| 496 | addr, | ||
| 497 | addr->v4.sin_port, | ||
| 498 | peer_state == SCTP_UNKNOWN?"UNKNOWN":"ACTIVE"); | ||
| 499 | |||
| 445 | /* Set the port if it has not been set yet. */ | 500 | /* Set the port if it has not been set yet. */ |
| 446 | if (0 == asoc->peer.port) | 501 | if (0 == asoc->peer.port) |
| 447 | asoc->peer.port = port; | 502 | asoc->peer.port = port; |
| 448 | 503 | ||
| 449 | /* Check to see if this is a duplicate. */ | 504 | /* Check to see if this is a duplicate. */ |
| 450 | peer = sctp_assoc_lookup_paddr(asoc, addr); | 505 | peer = sctp_assoc_lookup_paddr(asoc, addr); |
| 451 | if (peer) | 506 | if (peer) { |
| 507 | if (peer_state == SCTP_ACTIVE && | ||
| 508 | peer->state == SCTP_UNKNOWN) | ||
| 509 | peer->state = SCTP_ACTIVE; | ||
| 452 | return peer; | 510 | return peer; |
| 511 | } | ||
| 453 | 512 | ||
| 454 | peer = sctp_transport_new(addr, gfp); | 513 | peer = sctp_transport_new(addr, gfp); |
| 455 | if (!peer) | 514 | if (!peer) |
| @@ -516,8 +575,12 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
| 516 | /* Set the transport's RTO.initial value */ | 575 | /* Set the transport's RTO.initial value */ |
| 517 | peer->rto = asoc->rto_initial; | 576 | peer->rto = asoc->rto_initial; |
| 518 | 577 | ||
| 578 | /* Set the peer's active state. */ | ||
| 579 | peer->state = peer_state; | ||
| 580 | |||
| 519 | /* Attach the remote transport to our asoc. */ | 581 | /* Attach the remote transport to our asoc. */ |
| 520 | list_add_tail(&peer->transports, &asoc->peer.transport_addr_list); | 582 | list_add_tail(&peer->transports, &asoc->peer.transport_addr_list); |
| 583 | asoc->peer.transport_count++; | ||
| 521 | 584 | ||
| 522 | /* If we do not yet have a primary path, set one. */ | 585 | /* If we do not yet have a primary path, set one. */ |
| 523 | if (!asoc->peer.primary_path) { | 586 | if (!asoc->peer.primary_path) { |
| @@ -525,8 +588,9 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
| 525 | asoc->peer.retran_path = peer; | 588 | asoc->peer.retran_path = peer; |
| 526 | } | 589 | } |
| 527 | 590 | ||
| 528 | if (asoc->peer.active_path == asoc->peer.retran_path) | 591 | if (asoc->peer.active_path == asoc->peer.retran_path) { |
| 529 | asoc->peer.retran_path = peer; | 592 | asoc->peer.retran_path = peer; |
| 593 | } | ||
| 530 | 594 | ||
| 531 | return peer; | 595 | return peer; |
| 532 | } | 596 | } |
| @@ -537,37 +601,16 @@ void sctp_assoc_del_peer(struct sctp_association *asoc, | |||
| 537 | { | 601 | { |
| 538 | struct list_head *pos; | 602 | struct list_head *pos; |
| 539 | struct list_head *temp; | 603 | struct list_head *temp; |
| 540 | struct sctp_transport *peer = NULL; | ||
| 541 | struct sctp_transport *transport; | 604 | struct sctp_transport *transport; |
| 542 | 605 | ||
| 543 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { | 606 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { |
| 544 | transport = list_entry(pos, struct sctp_transport, transports); | 607 | transport = list_entry(pos, struct sctp_transport, transports); |
| 545 | if (sctp_cmp_addr_exact(addr, &transport->ipaddr)) { | 608 | if (sctp_cmp_addr_exact(addr, &transport->ipaddr)) { |
| 546 | peer = transport; | 609 | /* Do book keeping for removing the peer and free it. */ |
| 547 | list_del(pos); | 610 | sctp_assoc_rm_peer(asoc, transport); |
| 548 | break; | 611 | break; |
| 549 | } | 612 | } |
| 550 | } | 613 | } |
| 551 | |||
| 552 | /* The address we want delete is not in the association. */ | ||
| 553 | if (!peer) | ||
| 554 | return; | ||
| 555 | |||
| 556 | /* Get the first transport of asoc. */ | ||
| 557 | pos = asoc->peer.transport_addr_list.next; | ||
| 558 | transport = list_entry(pos, struct sctp_transport, transports); | ||
| 559 | |||
| 560 | /* Update any entries that match the peer to be deleted. */ | ||
| 561 | if (asoc->peer.primary_path == peer) | ||
| 562 | sctp_assoc_set_primary(asoc, transport); | ||
| 563 | if (asoc->peer.active_path == peer) | ||
| 564 | asoc->peer.active_path = transport; | ||
| 565 | if (asoc->peer.retran_path == peer) | ||
| 566 | asoc->peer.retran_path = transport; | ||
| 567 | if (asoc->peer.last_data_from == peer) | ||
| 568 | asoc->peer.last_data_from = transport; | ||
| 569 | |||
| 570 | sctp_transport_free(peer); | ||
| 571 | } | 614 | } |
| 572 | 615 | ||
| 573 | /* Lookup a transport by address. */ | 616 | /* Lookup a transport by address. */ |
| @@ -608,12 +651,12 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, | |||
| 608 | /* Record the transition on the transport. */ | 651 | /* Record the transition on the transport. */ |
| 609 | switch (command) { | 652 | switch (command) { |
| 610 | case SCTP_TRANSPORT_UP: | 653 | case SCTP_TRANSPORT_UP: |
| 611 | transport->active = SCTP_ACTIVE; | 654 | transport->state = SCTP_ACTIVE; |
| 612 | spc_state = SCTP_ADDR_AVAILABLE; | 655 | spc_state = SCTP_ADDR_AVAILABLE; |
| 613 | break; | 656 | break; |
| 614 | 657 | ||
| 615 | case SCTP_TRANSPORT_DOWN: | 658 | case SCTP_TRANSPORT_DOWN: |
| 616 | transport->active = SCTP_INACTIVE; | 659 | transport->state = SCTP_INACTIVE; |
| 617 | spc_state = SCTP_ADDR_UNREACHABLE; | 660 | spc_state = SCTP_ADDR_UNREACHABLE; |
| 618 | break; | 661 | break; |
| 619 | 662 | ||
| @@ -643,7 +686,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, | |||
| 643 | list_for_each(pos, &asoc->peer.transport_addr_list) { | 686 | list_for_each(pos, &asoc->peer.transport_addr_list) { |
| 644 | t = list_entry(pos, struct sctp_transport, transports); | 687 | t = list_entry(pos, struct sctp_transport, transports); |
| 645 | 688 | ||
| 646 | if (!t->active) | 689 | if (t->state == SCTP_INACTIVE) |
| 647 | continue; | 690 | continue; |
| 648 | if (!first || t->last_time_heard > first->last_time_heard) { | 691 | if (!first || t->last_time_heard > first->last_time_heard) { |
| 649 | second = first; | 692 | second = first; |
| @@ -663,7 +706,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, | |||
| 663 | * [If the primary is active but not most recent, bump the most | 706 | * [If the primary is active but not most recent, bump the most |
| 664 | * recently used transport.] | 707 | * recently used transport.] |
| 665 | */ | 708 | */ |
| 666 | if (asoc->peer.primary_path->active && | 709 | if (asoc->peer.primary_path->state != SCTP_INACTIVE && |
| 667 | first != asoc->peer.primary_path) { | 710 | first != asoc->peer.primary_path) { |
| 668 | second = first; | 711 | second = first; |
| 669 | first = asoc->peer.primary_path; | 712 | first = asoc->peer.primary_path; |
| @@ -958,7 +1001,7 @@ void sctp_assoc_update(struct sctp_association *asoc, | |||
| 958 | transports); | 1001 | transports); |
| 959 | if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr)) | 1002 | if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr)) |
| 960 | sctp_assoc_add_peer(asoc, &trans->ipaddr, | 1003 | sctp_assoc_add_peer(asoc, &trans->ipaddr, |
| 961 | GFP_ATOMIC); | 1004 | GFP_ATOMIC, SCTP_ACTIVE); |
| 962 | } | 1005 | } |
| 963 | 1006 | ||
| 964 | asoc->ctsn_ack_point = asoc->next_tsn - 1; | 1007 | asoc->ctsn_ack_point = asoc->next_tsn - 1; |
| @@ -998,7 +1041,7 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) | |||
| 998 | 1041 | ||
| 999 | /* Try to find an active transport. */ | 1042 | /* Try to find an active transport. */ |
| 1000 | 1043 | ||
| 1001 | if (t->active) { | 1044 | if (t->state != SCTP_INACTIVE) { |
| 1002 | break; | 1045 | break; |
| 1003 | } else { | 1046 | } else { |
| 1004 | /* Keep track of the next transport in case | 1047 | /* Keep track of the next transport in case |
| @@ -1019,6 +1062,40 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) | |||
| 1019 | } | 1062 | } |
| 1020 | 1063 | ||
| 1021 | asoc->peer.retran_path = t; | 1064 | asoc->peer.retran_path = t; |
| 1065 | |||
| 1066 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association" | ||
| 1067 | " %p addr: ", | ||
| 1068 | " port: %d\n", | ||
| 1069 | asoc, | ||
| 1070 | (&t->ipaddr), | ||
| 1071 | t->ipaddr.v4.sin_port); | ||
| 1072 | } | ||
| 1073 | |||
| 1074 | /* Choose the transport for sending a INIT packet. */ | ||
| 1075 | struct sctp_transport *sctp_assoc_choose_init_transport( | ||
| 1076 | struct sctp_association *asoc) | ||
| 1077 | { | ||
| 1078 | struct sctp_transport *t; | ||
| 1079 | |||
| 1080 | /* Use the retran path. If the last INIT was sent over the | ||
| 1081 | * retran path, update the retran path and use it. | ||
| 1082 | */ | ||
| 1083 | if (!asoc->init_last_sent_to) { | ||
| 1084 | t = asoc->peer.active_path; | ||
| 1085 | } else { | ||
| 1086 | if (asoc->init_last_sent_to == asoc->peer.retran_path) | ||
| 1087 | sctp_assoc_update_retran_path(asoc); | ||
| 1088 | t = asoc->peer.retran_path; | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association" | ||
| 1092 | " %p addr: ", | ||
| 1093 | " port: %d\n", | ||
| 1094 | asoc, | ||
| 1095 | (&t->ipaddr), | ||
| 1096 | t->ipaddr.v4.sin_port); | ||
| 1097 | |||
| 1098 | return t; | ||
| 1022 | } | 1099 | } |
| 1023 | 1100 | ||
| 1024 | /* Choose the transport for sending a SHUTDOWN packet. */ | 1101 | /* Choose the transport for sending a SHUTDOWN packet. */ |
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 334f61773e6d..2ec0320fac3b 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c | |||
| @@ -134,7 +134,6 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, | |||
| 134 | ep->last_key = ep->current_key = 0; | 134 | ep->last_key = ep->current_key = 0; |
| 135 | ep->key_changed_at = jiffies; | 135 | ep->key_changed_at = jiffies; |
| 136 | 136 | ||
| 137 | ep->debug_name = "unnamedEndpoint"; | ||
| 138 | return ep; | 137 | return ep; |
| 139 | } | 138 | } |
| 140 | 139 | ||
diff --git a/net/sctp/input.c b/net/sctp/input.c index fffc880a646d..339f7acfdb64 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
| @@ -353,7 +353,7 @@ void sctp_icmp_proto_unreachable(struct sock *sk, | |||
| 353 | 353 | ||
| 354 | sctp_do_sm(SCTP_EVENT_T_OTHER, | 354 | sctp_do_sm(SCTP_EVENT_T_OTHER, |
| 355 | SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), | 355 | SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), |
| 356 | asoc->state, asoc->ep, asoc, NULL, | 356 | asoc->state, asoc->ep, asoc, t, |
| 357 | GFP_ATOMIC); | 357 | GFP_ATOMIC); |
| 358 | 358 | ||
| 359 | } | 359 | } |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 1b2d4adc4ddb..4eb81a1407b7 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
| @@ -682,9 +682,9 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
| 682 | 682 | ||
| 683 | if (!new_transport) { | 683 | if (!new_transport) { |
| 684 | new_transport = asoc->peer.active_path; | 684 | new_transport = asoc->peer.active_path; |
| 685 | } else if (!new_transport->active) { | 685 | } else if (new_transport->state == SCTP_INACTIVE) { |
| 686 | /* If the chunk is Heartbeat or Heartbeat Ack, | 686 | /* If the chunk is Heartbeat or Heartbeat Ack, |
| 687 | * send it to chunk->transport, even if it's | 687 | * send it to chunk->transport, even if it's |
| 688 | * inactive. | 688 | * inactive. |
| 689 | * | 689 | * |
| 690 | * 3.3.6 Heartbeat Acknowledgement: | 690 | * 3.3.6 Heartbeat Acknowledgement: |
| @@ -840,7 +840,8 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
| 840 | * Otherwise, we want to use the active path. | 840 | * Otherwise, we want to use the active path. |
| 841 | */ | 841 | */ |
| 842 | new_transport = chunk->transport; | 842 | new_transport = chunk->transport; |
| 843 | if (!new_transport || !new_transport->active) | 843 | if (!new_transport || |
| 844 | new_transport->state == SCTP_INACTIVE) | ||
| 844 | new_transport = asoc->peer.active_path; | 845 | new_transport = asoc->peer.active_path; |
| 845 | 846 | ||
| 846 | /* Change packets if necessary. */ | 847 | /* Change packets if necessary. */ |
| @@ -1454,7 +1455,7 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
| 1454 | /* Mark the destination transport address as | 1455 | /* Mark the destination transport address as |
| 1455 | * active if it is not so marked. | 1456 | * active if it is not so marked. |
| 1456 | */ | 1457 | */ |
| 1457 | if (!transport->active) { | 1458 | if (transport->state == SCTP_INACTIVE) { |
| 1458 | sctp_assoc_control_transport( | 1459 | sctp_assoc_control_transport( |
| 1459 | transport->asoc, | 1460 | transport->asoc, |
| 1460 | transport, | 1461 | transport, |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 33ac8bf47b0e..5baed9bb7de5 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
| @@ -1830,7 +1830,7 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, | |||
| 1830 | * be a a better choice than any of the embedded addresses. | 1830 | * be a a better choice than any of the embedded addresses. |
| 1831 | */ | 1831 | */ |
| 1832 | if (peer_addr) | 1832 | if (peer_addr) |
| 1833 | if(!sctp_assoc_add_peer(asoc, peer_addr, gfp)) | 1833 | if(!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE)) |
| 1834 | goto nomem; | 1834 | goto nomem; |
| 1835 | 1835 | ||
| 1836 | /* Process the initialization parameters. */ | 1836 | /* Process the initialization parameters. */ |
| @@ -1841,6 +1841,14 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, | |||
| 1841 | goto clean_up; | 1841 | goto clean_up; |
| 1842 | } | 1842 | } |
| 1843 | 1843 | ||
| 1844 | /* Walk list of transports, removing transports in the UNKNOWN state. */ | ||
| 1845 | list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) { | ||
| 1846 | transport = list_entry(pos, struct sctp_transport, transports); | ||
| 1847 | if (transport->state == SCTP_UNKNOWN) { | ||
| 1848 | sctp_assoc_rm_peer(asoc, transport); | ||
| 1849 | } | ||
| 1850 | } | ||
| 1851 | |||
| 1844 | /* The fixed INIT headers are always in network byte | 1852 | /* The fixed INIT headers are always in network byte |
| 1845 | * order. | 1853 | * order. |
| 1846 | */ | 1854 | */ |
| @@ -1906,7 +1914,8 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, | |||
| 1906 | * stream sequence number shall be set to 0. | 1914 | * stream sequence number shall be set to 0. |
| 1907 | */ | 1915 | */ |
| 1908 | 1916 | ||
| 1909 | /* Allocate storage for the negotiated streams if it is not a temporary * association. | 1917 | /* Allocate storage for the negotiated streams if it is not a temporary |
| 1918 | * association. | ||
| 1910 | */ | 1919 | */ |
| 1911 | if (!asoc->temp) { | 1920 | if (!asoc->temp) { |
| 1912 | int assoc_id; | 1921 | int assoc_id; |
| @@ -1952,6 +1961,9 @@ clean_up: | |||
| 1952 | list_del_init(pos); | 1961 | list_del_init(pos); |
| 1953 | sctp_transport_free(transport); | 1962 | sctp_transport_free(transport); |
| 1954 | } | 1963 | } |
| 1964 | |||
| 1965 | asoc->peer.transport_count = 0; | ||
| 1966 | |||
| 1955 | nomem: | 1967 | nomem: |
| 1956 | return 0; | 1968 | return 0; |
| 1957 | } | 1969 | } |
| @@ -1995,7 +2007,7 @@ static int sctp_process_param(struct sctp_association *asoc, | |||
| 1995 | af->from_addr_param(&addr, param.addr, asoc->peer.port, 0); | 2007 | af->from_addr_param(&addr, param.addr, asoc->peer.port, 0); |
| 1996 | scope = sctp_scope(peer_addr); | 2008 | scope = sctp_scope(peer_addr); |
| 1997 | if (sctp_in_scope(&addr, scope)) | 2009 | if (sctp_in_scope(&addr, scope)) |
| 1998 | if (!sctp_assoc_add_peer(asoc, &addr, gfp)) | 2010 | if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_ACTIVE)) |
| 1999 | return 0; | 2011 | return 0; |
| 2000 | break; | 2012 | break; |
| 2001 | 2013 | ||
| @@ -2396,7 +2408,7 @@ static __u16 sctp_process_asconf_param(struct sctp_association *asoc, | |||
| 2396 | * Due to Resource Shortage'. | 2408 | * Due to Resource Shortage'. |
| 2397 | */ | 2409 | */ |
| 2398 | 2410 | ||
| 2399 | peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC); | 2411 | peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC, SCTP_ACTIVE); |
| 2400 | if (!peer) | 2412 | if (!peer) |
| 2401 | return SCTP_ERROR_RSRC_LOW; | 2413 | return SCTP_ERROR_RSRC_LOW; |
| 2402 | 2414 | ||
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index f65fa441952f..778639db125a 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
| @@ -414,11 +414,13 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, | |||
| 414 | */ | 414 | */ |
| 415 | asoc->overall_error_count++; | 415 | asoc->overall_error_count++; |
| 416 | 416 | ||
| 417 | if (transport->active && | 417 | if (transport->state != SCTP_INACTIVE && |
| 418 | (transport->error_count++ >= transport->max_retrans)) { | 418 | (transport->error_count++ >= transport->max_retrans)) { |
| 419 | SCTP_DEBUG_PRINTK("transport_strike: transport " | 419 | SCTP_DEBUG_PRINTK_IPADDR("transport_strike:association %p", |
| 420 | "IP:%d.%d.%d.%d failed.\n", | 420 | " transport IP: port:%d failed.\n", |
| 421 | NIPQUAD(transport->ipaddr.v4.sin_addr)); | 421 | asoc, |
| 422 | (&transport->ipaddr), | ||
| 423 | transport->ipaddr.v4.sin_port); | ||
| 422 | sctp_assoc_control_transport(asoc, transport, | 424 | sctp_assoc_control_transport(asoc, transport, |
| 423 | SCTP_TRANSPORT_DOWN, | 425 | SCTP_TRANSPORT_DOWN, |
| 424 | SCTP_FAILED_THRESHOLD); | 426 | SCTP_FAILED_THRESHOLD); |
| @@ -593,7 +595,7 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds, | |||
| 593 | /* Mark the destination transport address as active if it is not so | 595 | /* Mark the destination transport address as active if it is not so |
| 594 | * marked. | 596 | * marked. |
| 595 | */ | 597 | */ |
| 596 | if (!t->active) | 598 | if (t->state == SCTP_INACTIVE) |
| 597 | sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP, | 599 | sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP, |
| 598 | SCTP_HEARTBEAT_SUCCESS); | 600 | SCTP_HEARTBEAT_SUCCESS); |
| 599 | 601 | ||
| @@ -665,8 +667,11 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, | |||
| 665 | 667 | ||
| 666 | asoc->state = state; | 668 | asoc->state = state; |
| 667 | 669 | ||
| 670 | SCTP_DEBUG_PRINTK("sctp_cmd_new_state: asoc %p[%s]\n", | ||
| 671 | asoc, sctp_state_tbl[state]); | ||
| 672 | |||
| 668 | if (sctp_style(sk, TCP)) { | 673 | if (sctp_style(sk, TCP)) { |
| 669 | /* Change the sk->sk_state of a TCP-style socket that has | 674 | /* Change the sk->sk_state of a TCP-style socket that has |
| 670 | * sucessfully completed a connect() call. | 675 | * sucessfully completed a connect() call. |
| 671 | */ | 676 | */ |
| 672 | if (sctp_state(asoc, ESTABLISHED) && sctp_sstate(sk, CLOSED)) | 677 | if (sctp_state(asoc, ESTABLISHED) && sctp_sstate(sk, CLOSED)) |
| @@ -678,6 +683,16 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds, | |||
| 678 | sk->sk_shutdown |= RCV_SHUTDOWN; | 683 | sk->sk_shutdown |= RCV_SHUTDOWN; |
| 679 | } | 684 | } |
| 680 | 685 | ||
| 686 | if (sctp_state(asoc, COOKIE_WAIT)) { | ||
| 687 | /* Reset init timeouts since they may have been | ||
| 688 | * increased due to timer expirations. | ||
| 689 | */ | ||
| 690 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] = | ||
| 691 | asoc->ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]; | ||
| 692 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] = | ||
| 693 | asoc->ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]; | ||
| 694 | } | ||
| 695 | |||
| 681 | if (sctp_state(asoc, ESTABLISHED) || | 696 | if (sctp_state(asoc, ESTABLISHED) || |
| 682 | sctp_state(asoc, CLOSED) || | 697 | sctp_state(asoc, CLOSED) || |
| 683 | sctp_state(asoc, SHUTDOWN_RECEIVED)) { | 698 | sctp_state(asoc, SHUTDOWN_RECEIVED)) { |
| @@ -1120,10 +1135,10 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
| 1120 | * to be executed only during failed attempts of | 1135 | * to be executed only during failed attempts of |
| 1121 | * association establishment. | 1136 | * association establishment. |
| 1122 | */ | 1137 | */ |
| 1123 | if ((asoc->peer.retran_path != | 1138 | if ((asoc->peer.retran_path != |
| 1124 | asoc->peer.primary_path) && | 1139 | asoc->peer.primary_path) && |
| 1125 | (asoc->counters[SCTP_COUNTER_INIT_ERROR] > 0)) { | 1140 | (asoc->init_err_counter > 0)) { |
| 1126 | sctp_add_cmd_sf(commands, | 1141 | sctp_add_cmd_sf(commands, |
| 1127 | SCTP_CMD_FORCE_PRIM_RETRAN, | 1142 | SCTP_CMD_FORCE_PRIM_RETRAN, |
| 1128 | SCTP_NULL()); | 1143 | SCTP_NULL()); |
| 1129 | } | 1144 | } |
| @@ -1237,18 +1252,67 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
| 1237 | sctp_association_put(asoc); | 1252 | sctp_association_put(asoc); |
| 1238 | break; | 1253 | break; |
| 1239 | 1254 | ||
| 1255 | case SCTP_CMD_INIT_CHOOSE_TRANSPORT: | ||
| 1256 | chunk = cmd->obj.ptr; | ||
| 1257 | t = sctp_assoc_choose_init_transport(asoc); | ||
| 1258 | asoc->init_last_sent_to = t; | ||
| 1259 | chunk->transport = t; | ||
| 1260 | t->init_sent_count++; | ||
| 1261 | break; | ||
| 1262 | |||
| 1240 | case SCTP_CMD_INIT_RESTART: | 1263 | case SCTP_CMD_INIT_RESTART: |
| 1241 | /* Do the needed accounting and updates | 1264 | /* Do the needed accounting and updates |
| 1242 | * associated with restarting an initialization | 1265 | * associated with restarting an initialization |
| 1243 | * timer. | 1266 | * timer. Only multiply the timeout by two if |
| 1267 | * all transports have been tried at the current | ||
| 1268 | * timeout. | ||
| 1269 | */ | ||
| 1270 | t = asoc->init_last_sent_to; | ||
| 1271 | asoc->init_err_counter++; | ||
| 1272 | |||
| 1273 | if (t->init_sent_count > (asoc->init_cycle + 1)) { | ||
| 1274 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] *= 2; | ||
| 1275 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] > | ||
| 1276 | asoc->max_init_timeo) { | ||
| 1277 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] = | ||
| 1278 | asoc->max_init_timeo; | ||
| 1279 | } | ||
| 1280 | asoc->init_cycle++; | ||
| 1281 | SCTP_DEBUG_PRINTK( | ||
| 1282 | "T1 INIT Timeout adjustment" | ||
| 1283 | " init_err_counter: %d" | ||
| 1284 | " cycle: %d" | ||
| 1285 | " timeout: %d\n", | ||
| 1286 | asoc->init_err_counter, | ||
| 1287 | asoc->init_cycle, | ||
| 1288 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]); | ||
| 1289 | } | ||
| 1290 | |||
| 1291 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART, | ||
| 1292 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); | ||
| 1293 | break; | ||
| 1294 | |||
| 1295 | case SCTP_CMD_COOKIEECHO_RESTART: | ||
| 1296 | /* Do the needed accounting and updates | ||
| 1297 | * associated with restarting an initialization | ||
| 1298 | * timer. Only multiply the timeout by two if | ||
| 1299 | * all transports have been tried at the current | ||
| 1300 | * timeout. | ||
| 1244 | */ | 1301 | */ |
| 1245 | asoc->counters[SCTP_COUNTER_INIT_ERROR]++; | 1302 | asoc->init_err_counter++; |
| 1246 | asoc->timeouts[cmd->obj.to] *= 2; | 1303 | |
| 1247 | if (asoc->timeouts[cmd->obj.to] > | 1304 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] *= 2; |
| 1305 | if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] > | ||
| 1248 | asoc->max_init_timeo) { | 1306 | asoc->max_init_timeo) { |
| 1249 | asoc->timeouts[cmd->obj.to] = | 1307 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] = |
| 1250 | asoc->max_init_timeo; | 1308 | asoc->max_init_timeo; |
| 1251 | } | 1309 | } |
| 1310 | SCTP_DEBUG_PRINTK( | ||
| 1311 | "T1 COOKIE Timeout adjustment" | ||
| 1312 | " init_err_counter: %d" | ||
| 1313 | " timeout: %d\n", | ||
| 1314 | asoc->init_err_counter, | ||
| 1315 | asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]); | ||
| 1252 | 1316 | ||
| 1253 | /* If we've sent any data bundled with | 1317 | /* If we've sent any data bundled with |
| 1254 | * COOKIE-ECHO we need to resend. | 1318 | * COOKIE-ECHO we need to resend. |
| @@ -1261,7 +1325,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
| 1261 | 1325 | ||
| 1262 | sctp_add_cmd_sf(commands, | 1326 | sctp_add_cmd_sf(commands, |
| 1263 | SCTP_CMD_TIMER_RESTART, | 1327 | SCTP_CMD_TIMER_RESTART, |
| 1264 | SCTP_TO(cmd->obj.to)); | 1328 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); |
| 1265 | break; | 1329 | break; |
| 1266 | 1330 | ||
| 1267 | case SCTP_CMD_INIT_FAILED: | 1331 | case SCTP_CMD_INIT_FAILED: |
| @@ -1273,12 +1337,13 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
| 1273 | subtype, chunk, cmd->obj.u32); | 1337 | subtype, chunk, cmd->obj.u32); |
| 1274 | break; | 1338 | break; |
| 1275 | 1339 | ||
| 1276 | case SCTP_CMD_COUNTER_INC: | 1340 | case SCTP_CMD_INIT_COUNTER_INC: |
| 1277 | asoc->counters[cmd->obj.counter]++; | 1341 | asoc->init_err_counter++; |
| 1278 | break; | 1342 | break; |
| 1279 | 1343 | ||
| 1280 | case SCTP_CMD_COUNTER_RESET: | 1344 | case SCTP_CMD_INIT_COUNTER_RESET: |
| 1281 | asoc->counters[cmd->obj.counter] = 0; | 1345 | asoc->init_err_counter = 0; |
| 1346 | asoc->init_cycle = 0; | ||
| 1282 | break; | 1347 | break; |
| 1283 | 1348 | ||
| 1284 | case SCTP_CMD_REPORT_DUP: | 1349 | case SCTP_CMD_REPORT_DUP: |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 8e01b8f09ac2..058189684c7c 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
| @@ -533,6 +533,9 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep, | |||
| 533 | sctp_add_cmd_sf(commands, SCTP_CMD_PEER_INIT, | 533 | sctp_add_cmd_sf(commands, SCTP_CMD_PEER_INIT, |
| 534 | SCTP_PEER_INIT(initchunk)); | 534 | SCTP_PEER_INIT(initchunk)); |
| 535 | 535 | ||
| 536 | /* Reset init error count upon receipt of INIT-ACK. */ | ||
| 537 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL()); | ||
| 538 | |||
| 536 | /* 5.1 C) "A" shall stop the T1-init timer and leave | 539 | /* 5.1 C) "A" shall stop the T1-init timer and leave |
| 537 | * COOKIE-WAIT state. "A" shall then ... start the T1-cookie | 540 | * COOKIE-WAIT state. "A" shall then ... start the T1-cookie |
| 538 | * timer, and enter the COOKIE-ECHOED state. | 541 | * timer, and enter the COOKIE-ECHOED state. |
| @@ -775,8 +778,7 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep, | |||
| 775 | * from the COOKIE-ECHOED state to the COOKIE-WAIT | 778 | * from the COOKIE-ECHOED state to the COOKIE-WAIT |
| 776 | * state is performed. | 779 | * state is performed. |
| 777 | */ | 780 | */ |
| 778 | sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_RESET, | 781 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL()); |
| 779 | SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR)); | ||
| 780 | 782 | ||
| 781 | /* RFC 2960 5.1 Normal Establishment of an Association | 783 | /* RFC 2960 5.1 Normal Establishment of an Association |
| 782 | * | 784 | * |
| @@ -1019,10 +1021,22 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep, | |||
| 1019 | link = sctp_assoc_lookup_paddr(asoc, &from_addr); | 1021 | link = sctp_assoc_lookup_paddr(asoc, &from_addr); |
| 1020 | 1022 | ||
| 1021 | /* This should never happen, but lets log it if so. */ | 1023 | /* This should never happen, but lets log it if so. */ |
| 1022 | if (!link) { | 1024 | if (unlikely(!link)) { |
| 1023 | printk(KERN_WARNING | 1025 | if (from_addr.sa.sa_family == AF_INET6) { |
| 1024 | "%s: Could not find address %d.%d.%d.%d\n", | 1026 | printk(KERN_WARNING |
| 1025 | __FUNCTION__, NIPQUAD(from_addr.v4.sin_addr)); | 1027 | "%s association %p could not find address " |
| 1028 | "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | ||
| 1029 | __FUNCTION__, | ||
| 1030 | asoc, | ||
| 1031 | NIP6(from_addr.v6.sin6_addr)); | ||
| 1032 | } else { | ||
| 1033 | printk(KERN_WARNING | ||
| 1034 | "%s association %p could not find address " | ||
| 1035 | "%u.%u.%u.%u\n", | ||
| 1036 | __FUNCTION__, | ||
| 1037 | asoc, | ||
| 1038 | NIPQUAD(from_addr.v4.sin_addr.s_addr)); | ||
| 1039 | } | ||
| 1026 | return SCTP_DISPOSITION_DISCARD; | 1040 | return SCTP_DISPOSITION_DISCARD; |
| 1027 | } | 1041 | } |
| 1028 | 1042 | ||
| @@ -2095,9 +2109,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep, | |||
| 2095 | sctp_errhdr_t *err; | 2109 | sctp_errhdr_t *err; |
| 2096 | struct sctp_chunk *reply; | 2110 | struct sctp_chunk *reply; |
| 2097 | struct sctp_bind_addr *bp; | 2111 | struct sctp_bind_addr *bp; |
| 2098 | int attempts; | 2112 | int attempts = asoc->init_err_counter + 1; |
| 2099 | |||
| 2100 | attempts = asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1; | ||
| 2101 | 2113 | ||
| 2102 | if (attempts >= asoc->max_init_attempts) { | 2114 | if (attempts >= asoc->max_init_attempts) { |
| 2103 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | 2115 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, |
| @@ -2157,8 +2169,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep, | |||
| 2157 | /* Cast away the const modifier, as we want to just | 2169 | /* Cast away the const modifier, as we want to just |
| 2158 | * rerun it through as a sideffect. | 2170 | * rerun it through as a sideffect. |
| 2159 | */ | 2171 | */ |
| 2160 | sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_INC, | 2172 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_INC, SCTP_NULL()); |
| 2161 | SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR)); | ||
| 2162 | 2173 | ||
| 2163 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 2174 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
| 2164 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); | 2175 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); |
| @@ -2281,8 +2292,7 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep, | |||
| 2281 | if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) | 2292 | if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) |
| 2282 | error = ((sctp_errhdr_t *)chunk->skb->data)->cause; | 2293 | error = ((sctp_errhdr_t *)chunk->skb->data)->cause; |
| 2283 | 2294 | ||
| 2284 | sctp_stop_t1_and_abort(commands, error); | 2295 | return sctp_stop_t1_and_abort(commands, error, asoc, chunk->transport); |
| 2285 | return SCTP_DISPOSITION_ABORT; | ||
| 2286 | } | 2296 | } |
| 2287 | 2297 | ||
| 2288 | /* | 2298 | /* |
| @@ -2294,8 +2304,8 @@ sctp_disposition_t sctp_sf_cookie_wait_icmp_abort(const struct sctp_endpoint *ep | |||
| 2294 | void *arg, | 2304 | void *arg, |
| 2295 | sctp_cmd_seq_t *commands) | 2305 | sctp_cmd_seq_t *commands) |
| 2296 | { | 2306 | { |
| 2297 | sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR); | 2307 | return sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR, asoc, |
| 2298 | return SCTP_DISPOSITION_ABORT; | 2308 | (struct sctp_transport *)arg); |
| 2299 | } | 2309 | } |
| 2300 | 2310 | ||
| 2301 | /* | 2311 | /* |
| @@ -2318,8 +2328,12 @@ sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep, | |||
| 2318 | * | 2328 | * |
| 2319 | * This is common code called by several sctp_sf_*_abort() functions above. | 2329 | * This is common code called by several sctp_sf_*_abort() functions above. |
| 2320 | */ | 2330 | */ |
| 2321 | void sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, __u16 error) | 2331 | sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, |
| 2332 | __u16 error, | ||
| 2333 | const struct sctp_association *asoc, | ||
| 2334 | struct sctp_transport *transport) | ||
| 2322 | { | 2335 | { |
| 2336 | SCTP_DEBUG_PRINTK("ABORT received (INIT).\n"); | ||
| 2323 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 2337 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, |
| 2324 | SCTP_STATE(SCTP_STATE_CLOSED)); | 2338 | SCTP_STATE(SCTP_STATE_CLOSED)); |
| 2325 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 2339 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); |
| @@ -2328,6 +2342,7 @@ void sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, __u16 error) | |||
| 2328 | /* CMD_INIT_FAILED will DELETE_TCB. */ | 2342 | /* CMD_INIT_FAILED will DELETE_TCB. */ |
| 2329 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | 2343 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, |
| 2330 | SCTP_U32(error)); | 2344 | SCTP_U32(error)); |
| 2345 | return SCTP_DISPOSITION_ABORT; | ||
| 2331 | } | 2346 | } |
| 2332 | 2347 | ||
| 2333 | /* | 2348 | /* |
| @@ -3805,6 +3820,10 @@ sctp_disposition_t sctp_sf_do_prm_asoc(const struct sctp_endpoint *ep, | |||
| 3805 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, | 3820 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, |
| 3806 | SCTP_ASOC((struct sctp_association *) asoc)); | 3821 | SCTP_ASOC((struct sctp_association *) asoc)); |
| 3807 | 3822 | ||
| 3823 | /* Choose transport for INIT. */ | ||
| 3824 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT, | ||
| 3825 | SCTP_CHUNK(repl)); | ||
| 3826 | |||
| 3808 | /* After sending the INIT, "A" starts the T1-init timer and | 3827 | /* After sending the INIT, "A" starts the T1-init timer and |
| 3809 | * enters the COOKIE-WAIT state. | 3828 | * enters the COOKIE-WAIT state. |
| 3810 | */ | 3829 | */ |
| @@ -4589,7 +4608,7 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep, | |||
| 4589 | } | 4608 | } |
| 4590 | 4609 | ||
| 4591 | /* | 4610 | /* |
| 4592 | * sctp_sf_t1_timer_expire | 4611 | * sctp_sf_t1_init_timer_expire |
| 4593 | * | 4612 | * |
| 4594 | * Section: 4 Note: 2 | 4613 | * Section: 4 Note: 2 |
| 4595 | * Verification Tag: | 4614 | * Verification Tag: |
| @@ -4603,7 +4622,59 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep, | |||
| 4603 | * endpoint MUST abort the initialization process and report the | 4622 | * endpoint MUST abort the initialization process and report the |
| 4604 | * error to SCTP user. | 4623 | * error to SCTP user. |
| 4605 | * | 4624 | * |
| 4606 | * 3) If the T1-cookie timer expires, the endpoint MUST retransmit | 4625 | * Outputs |
| 4626 | * (timers, events) | ||
| 4627 | * | ||
| 4628 | */ | ||
| 4629 | sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep, | ||
| 4630 | const struct sctp_association *asoc, | ||
| 4631 | const sctp_subtype_t type, | ||
| 4632 | void *arg, | ||
| 4633 | sctp_cmd_seq_t *commands) | ||
| 4634 | { | ||
| 4635 | struct sctp_chunk *repl = NULL; | ||
| 4636 | struct sctp_bind_addr *bp; | ||
| 4637 | int attempts = asoc->init_err_counter + 1; | ||
| 4638 | |||
| 4639 | SCTP_DEBUG_PRINTK("Timer T1 expired (INIT).\n"); | ||
| 4640 | |||
| 4641 | if (attempts < asoc->max_init_attempts) { | ||
| 4642 | bp = (struct sctp_bind_addr *) &asoc->base.bind_addr; | ||
| 4643 | repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0); | ||
| 4644 | if (!repl) | ||
| 4645 | return SCTP_DISPOSITION_NOMEM; | ||
| 4646 | |||
| 4647 | /* Choose transport for INIT. */ | ||
| 4648 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT, | ||
| 4649 | SCTP_CHUNK(repl)); | ||
| 4650 | |||
| 4651 | /* Issue a sideeffect to do the needed accounting. */ | ||
| 4652 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_RESTART, | ||
| 4653 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); | ||
| 4654 | |||
| 4655 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); | ||
| 4656 | } else { | ||
| 4657 | SCTP_DEBUG_PRINTK("Giving up on INIT, attempts: %d" | ||
| 4658 | " max_init_attempts: %d\n", | ||
| 4659 | attempts, asoc->max_init_attempts); | ||
| 4660 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | ||
| 4661 | SCTP_U32(SCTP_ERROR_NO_ERROR)); | ||
| 4662 | return SCTP_DISPOSITION_DELETE_TCB; | ||
| 4663 | } | ||
| 4664 | |||
| 4665 | return SCTP_DISPOSITION_CONSUME; | ||
| 4666 | } | ||
| 4667 | |||
| 4668 | /* | ||
| 4669 | * sctp_sf_t1_cookie_timer_expire | ||
| 4670 | * | ||
| 4671 | * Section: 4 Note: 2 | ||
| 4672 | * Verification Tag: | ||
| 4673 | * Inputs | ||
| 4674 | * (endpoint, asoc) | ||
| 4675 | * | ||
| 4676 | * RFC 2960 Section 4 Notes | ||
| 4677 | * 3) If the T1-cookie timer expires, the endpoint MUST retransmit | ||
| 4607 | * COOKIE ECHO and re-start the T1-cookie timer without changing | 4678 | * COOKIE ECHO and re-start the T1-cookie timer without changing |
| 4608 | * state. This MUST be repeated up to 'Max.Init.Retransmits' times. | 4679 | * state. This MUST be repeated up to 'Max.Init.Retransmits' times. |
| 4609 | * After that, the endpoint MUST abort the initialization process and | 4680 | * After that, the endpoint MUST abort the initialization process and |
| @@ -4613,46 +4684,26 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep, | |||
| 4613 | * (timers, events) | 4684 | * (timers, events) |
| 4614 | * | 4685 | * |
| 4615 | */ | 4686 | */ |
| 4616 | sctp_disposition_t sctp_sf_t1_timer_expire(const struct sctp_endpoint *ep, | 4687 | sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep, |
| 4617 | const struct sctp_association *asoc, | 4688 | const struct sctp_association *asoc, |
| 4618 | const sctp_subtype_t type, | 4689 | const sctp_subtype_t type, |
| 4619 | void *arg, | 4690 | void *arg, |
| 4620 | sctp_cmd_seq_t *commands) | 4691 | sctp_cmd_seq_t *commands) |
| 4621 | { | 4692 | { |
| 4622 | struct sctp_chunk *repl; | 4693 | struct sctp_chunk *repl = NULL; |
| 4623 | struct sctp_bind_addr *bp; | 4694 | int attempts = asoc->init_err_counter + 1; |
| 4624 | sctp_event_timeout_t timer = (sctp_event_timeout_t) arg; | ||
| 4625 | int timeout; | ||
| 4626 | int attempts; | ||
| 4627 | |||
| 4628 | timeout = asoc->timeouts[timer]; | ||
| 4629 | attempts = asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1; | ||
| 4630 | repl = NULL; | ||
| 4631 | 4695 | ||
| 4632 | SCTP_DEBUG_PRINTK("Timer T1 expired.\n"); | 4696 | SCTP_DEBUG_PRINTK("Timer T1 expired (COOKIE-ECHO).\n"); |
| 4633 | 4697 | ||
| 4634 | if (attempts < asoc->max_init_attempts) { | 4698 | if (attempts < asoc->max_init_attempts) { |
| 4635 | switch (timer) { | 4699 | repl = sctp_make_cookie_echo(asoc, NULL); |
| 4636 | case SCTP_EVENT_TIMEOUT_T1_INIT: | ||
| 4637 | bp = (struct sctp_bind_addr *) &asoc->base.bind_addr; | ||
| 4638 | repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0); | ||
| 4639 | break; | ||
| 4640 | |||
| 4641 | case SCTP_EVENT_TIMEOUT_T1_COOKIE: | ||
| 4642 | repl = sctp_make_cookie_echo(asoc, NULL); | ||
| 4643 | break; | ||
| 4644 | |||
| 4645 | default: | ||
| 4646 | BUG(); | ||
| 4647 | break; | ||
| 4648 | }; | ||
| 4649 | |||
| 4650 | if (!repl) | 4700 | if (!repl) |
| 4651 | goto nomem; | 4701 | return SCTP_DISPOSITION_NOMEM; |
| 4652 | 4702 | ||
| 4653 | /* Issue a sideeffect to do the needed accounting. */ | 4703 | /* Issue a sideeffect to do the needed accounting. */ |
| 4654 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_RESTART, | 4704 | sctp_add_cmd_sf(commands, SCTP_CMD_COOKIEECHO_RESTART, |
| 4655 | SCTP_TO(timer)); | 4705 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); |
| 4706 | |||
| 4656 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); | 4707 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); |
| 4657 | } else { | 4708 | } else { |
| 4658 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, | 4709 | sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, |
| @@ -4661,9 +4712,6 @@ sctp_disposition_t sctp_sf_t1_timer_expire(const struct sctp_endpoint *ep, | |||
| 4661 | } | 4712 | } |
| 4662 | 4713 | ||
| 4663 | return SCTP_DISPOSITION_CONSUME; | 4714 | return SCTP_DISPOSITION_CONSUME; |
| 4664 | |||
| 4665 | nomem: | ||
| 4666 | return SCTP_DISPOSITION_NOMEM; | ||
| 4667 | } | 4715 | } |
| 4668 | 4716 | ||
| 4669 | /* RFC2960 9.2 If the timer expires, the endpoint must re-send the SHUTDOWN | 4717 | /* RFC2960 9.2 If the timer expires, the endpoint must re-send the SHUTDOWN |
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index 8967846f69e8..75ef10408764 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c | |||
| @@ -783,7 +783,8 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ | |||
| 783 | /* SCTP_STATE_COOKIE_WAIT */ \ | 783 | /* SCTP_STATE_COOKIE_WAIT */ \ |
| 784 | {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ | 784 | {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ |
| 785 | /* SCTP_STATE_COOKIE_ECHOED */ \ | 785 | /* SCTP_STATE_COOKIE_ECHOED */ \ |
| 786 | {.fn = sctp_sf_t1_timer_expire, .name = "sctp_sf_t1_timer_expire"}, \ | 786 | {.fn = sctp_sf_t1_cookie_timer_expire, \ |
| 787 | .name = "sctp_sf_t1_cookie_timer_expire"}, \ | ||
| 787 | /* SCTP_STATE_ESTABLISHED */ \ | 788 | /* SCTP_STATE_ESTABLISHED */ \ |
| 788 | {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ | 789 | {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ |
| 789 | /* SCTP_STATE_SHUTDOWN_PENDING */ \ | 790 | /* SCTP_STATE_SHUTDOWN_PENDING */ \ |
| @@ -802,7 +803,8 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ | |||
| 802 | /* SCTP_STATE_CLOSED */ \ | 803 | /* SCTP_STATE_CLOSED */ \ |
| 803 | {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ | 804 | {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ |
| 804 | /* SCTP_STATE_COOKIE_WAIT */ \ | 805 | /* SCTP_STATE_COOKIE_WAIT */ \ |
| 805 | {.fn = sctp_sf_t1_timer_expire, .name = "sctp_sf_t1_timer_expire"}, \ | 806 | {.fn = sctp_sf_t1_init_timer_expire, \ |
| 807 | .name = "sctp_sf_t1_init_timer_expire"}, \ | ||
| 806 | /* SCTP_STATE_COOKIE_ECHOED */ \ | 808 | /* SCTP_STATE_COOKIE_ECHOED */ \ |
| 807 | {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ | 809 | {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ |
| 808 | /* SCTP_STATE_ESTABLISHED */ \ | 810 | /* SCTP_STATE_ESTABLISHED */ \ |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index e6926cb19420..aad55dc3792b 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
| @@ -262,18 +262,18 @@ static struct sctp_transport *sctp_addr_id2transport(struct sock *sk, | |||
| 262 | * sockaddr_in6 [RFC 2553]), | 262 | * sockaddr_in6 [RFC 2553]), |
| 263 | * addr_len - the size of the address structure. | 263 | * addr_len - the size of the address structure. |
| 264 | */ | 264 | */ |
| 265 | SCTP_STATIC int sctp_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) | 265 | SCTP_STATIC int sctp_bind(struct sock *sk, struct sockaddr *addr, int addr_len) |
| 266 | { | 266 | { |
| 267 | int retval = 0; | 267 | int retval = 0; |
| 268 | 268 | ||
| 269 | sctp_lock_sock(sk); | 269 | sctp_lock_sock(sk); |
| 270 | 270 | ||
| 271 | SCTP_DEBUG_PRINTK("sctp_bind(sk: %p, uaddr: %p, addr_len: %d)\n", | 271 | SCTP_DEBUG_PRINTK("sctp_bind(sk: %p, addr: %p, addr_len: %d)\n", |
| 272 | sk, uaddr, addr_len); | 272 | sk, addr, addr_len); |
| 273 | 273 | ||
| 274 | /* Disallow binding twice. */ | 274 | /* Disallow binding twice. */ |
| 275 | if (!sctp_sk(sk)->ep->base.bind_addr.port) | 275 | if (!sctp_sk(sk)->ep->base.bind_addr.port) |
| 276 | retval = sctp_do_bind(sk, (union sctp_addr *)uaddr, | 276 | retval = sctp_do_bind(sk, (union sctp_addr *)addr, |
| 277 | addr_len); | 277 | addr_len); |
| 278 | else | 278 | else |
| 279 | retval = -EINVAL; | 279 | retval = -EINVAL; |
| @@ -318,23 +318,27 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) | |||
| 318 | unsigned short snum; | 318 | unsigned short snum; |
| 319 | int ret = 0; | 319 | int ret = 0; |
| 320 | 320 | ||
| 321 | SCTP_DEBUG_PRINTK("sctp_do_bind(sk: %p, newaddr: %p, len: %d)\n", | ||
| 322 | sk, addr, len); | ||
| 323 | |||
| 324 | /* Common sockaddr verification. */ | 321 | /* Common sockaddr verification. */ |
| 325 | af = sctp_sockaddr_af(sp, addr, len); | 322 | af = sctp_sockaddr_af(sp, addr, len); |
| 326 | if (!af) | 323 | if (!af) { |
| 324 | SCTP_DEBUG_PRINTK("sctp_do_bind(sk: %p, newaddr: %p, len: %d) EINVAL\n", | ||
| 325 | sk, addr, len); | ||
| 327 | return -EINVAL; | 326 | return -EINVAL; |
| 327 | } | ||
| 328 | |||
| 329 | snum = ntohs(addr->v4.sin_port); | ||
| 330 | |||
| 331 | SCTP_DEBUG_PRINTK_IPADDR("sctp_do_bind(sk: %p, new addr: ", | ||
| 332 | ", port: %d, new port: %d, len: %d)\n", | ||
| 333 | sk, | ||
| 334 | addr, | ||
| 335 | bp->port, snum, | ||
| 336 | len); | ||
| 328 | 337 | ||
| 329 | /* PF specific bind() address verification. */ | 338 | /* PF specific bind() address verification. */ |
| 330 | if (!sp->pf->bind_verify(sp, addr)) | 339 | if (!sp->pf->bind_verify(sp, addr)) |
| 331 | return -EADDRNOTAVAIL; | 340 | return -EADDRNOTAVAIL; |
| 332 | 341 | ||
| 333 | snum= ntohs(addr->v4.sin_port); | ||
| 334 | |||
| 335 | SCTP_DEBUG_PRINTK("sctp_do_bind: port: %d, new port: %d\n", | ||
| 336 | bp->port, snum); | ||
| 337 | |||
| 338 | /* We must either be unbound, or bind to the same port. */ | 342 | /* We must either be unbound, or bind to the same port. */ |
| 339 | if (bp->port && (snum != bp->port)) { | 343 | if (bp->port && (snum != bp->port)) { |
| 340 | SCTP_DEBUG_PRINTK("sctp_do_bind:" | 344 | SCTP_DEBUG_PRINTK("sctp_do_bind:" |
| @@ -816,7 +820,8 @@ out: | |||
| 816 | * | 820 | * |
| 817 | * Basically do nothing but copying the addresses from user to kernel | 821 | * Basically do nothing but copying the addresses from user to kernel |
| 818 | * land and invoking either sctp_bindx_add() or sctp_bindx_rem() on the sk. | 822 | * land and invoking either sctp_bindx_add() or sctp_bindx_rem() on the sk. |
| 819 | * This is used for tunneling the sctp_bindx() request through sctp_setsockopt() * from userspace. | 823 | * This is used for tunneling the sctp_bindx() request through sctp_setsockopt() |
| 824 | * from userspace. | ||
| 820 | * | 825 | * |
| 821 | * We don't use copy_from_user() for optimization: we first do the | 826 | * We don't use copy_from_user() for optimization: we first do the |
| 822 | * sanity checks (buffer size -fast- and access check-healthy | 827 | * sanity checks (buffer size -fast- and access check-healthy |
| @@ -913,6 +918,243 @@ out: | |||
| 913 | return err; | 918 | return err; |
| 914 | } | 919 | } |
| 915 | 920 | ||
| 921 | /* __sctp_connect(struct sock* sk, struct sockaddr *kaddrs, int addrs_size) | ||
| 922 | * | ||
| 923 | * Common routine for handling connect() and sctp_connectx(). | ||
| 924 | * Connect will come in with just a single address. | ||
| 925 | */ | ||
| 926 | static int __sctp_connect(struct sock* sk, | ||
| 927 | struct sockaddr *kaddrs, | ||
| 928 | int addrs_size) | ||
| 929 | { | ||
| 930 | struct sctp_sock *sp; | ||
| 931 | struct sctp_endpoint *ep; | ||
| 932 | struct sctp_association *asoc = NULL; | ||
| 933 | struct sctp_association *asoc2; | ||
| 934 | struct sctp_transport *transport; | ||
| 935 | union sctp_addr to; | ||
| 936 | struct sctp_af *af; | ||
| 937 | sctp_scope_t scope; | ||
| 938 | long timeo; | ||
| 939 | int err = 0; | ||
| 940 | int addrcnt = 0; | ||
| 941 | int walk_size = 0; | ||
| 942 | struct sockaddr *sa_addr; | ||
| 943 | void *addr_buf; | ||
| 944 | |||
| 945 | sp = sctp_sk(sk); | ||
| 946 | ep = sp->ep; | ||
| 947 | |||
| 948 | /* connect() cannot be done on a socket that is already in ESTABLISHED | ||
| 949 | * state - UDP-style peeled off socket or a TCP-style socket that | ||
| 950 | * is already connected. | ||
| 951 | * It cannot be done even on a TCP-style listening socket. | ||
| 952 | */ | ||
| 953 | if (sctp_sstate(sk, ESTABLISHED) || | ||
| 954 | (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) { | ||
| 955 | err = -EISCONN; | ||
| 956 | goto out_free; | ||
| 957 | } | ||
| 958 | |||
| 959 | /* Walk through the addrs buffer and count the number of addresses. */ | ||
| 960 | addr_buf = kaddrs; | ||
| 961 | while (walk_size < addrs_size) { | ||
| 962 | sa_addr = (struct sockaddr *)addr_buf; | ||
| 963 | af = sctp_get_af_specific(sa_addr->sa_family); | ||
| 964 | |||
| 965 | /* If the address family is not supported or if this address | ||
| 966 | * causes the address buffer to overflow return EINVAL. | ||
| 967 | */ | ||
| 968 | if (!af || (walk_size + af->sockaddr_len) > addrs_size) { | ||
| 969 | err = -EINVAL; | ||
| 970 | goto out_free; | ||
| 971 | } | ||
| 972 | |||
| 973 | err = sctp_verify_addr(sk, (union sctp_addr *)sa_addr, | ||
| 974 | af->sockaddr_len); | ||
| 975 | if (err) | ||
| 976 | goto out_free; | ||
| 977 | |||
| 978 | memcpy(&to, sa_addr, af->sockaddr_len); | ||
| 979 | to.v4.sin_port = ntohs(to.v4.sin_port); | ||
| 980 | |||
| 981 | /* Check if there already is a matching association on the | ||
| 982 | * endpoint (other than the one created here). | ||
| 983 | */ | ||
| 984 | asoc2 = sctp_endpoint_lookup_assoc(ep, &to, &transport); | ||
| 985 | if (asoc2 && asoc2 != asoc) { | ||
| 986 | if (asoc2->state >= SCTP_STATE_ESTABLISHED) | ||
| 987 | err = -EISCONN; | ||
| 988 | else | ||
| 989 | err = -EALREADY; | ||
| 990 | goto out_free; | ||
| 991 | } | ||
| 992 | |||
| 993 | /* If we could not find a matching association on the endpoint, | ||
| 994 | * make sure that there is no peeled-off association matching | ||
| 995 | * the peer address even on another socket. | ||
| 996 | */ | ||
| 997 | if (sctp_endpoint_is_peeled_off(ep, &to)) { | ||
| 998 | err = -EADDRNOTAVAIL; | ||
| 999 | goto out_free; | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | if (!asoc) { | ||
| 1003 | /* If a bind() or sctp_bindx() is not called prior to | ||
| 1004 | * an sctp_connectx() call, the system picks an | ||
| 1005 | * ephemeral port and will choose an address set | ||
| 1006 | * equivalent to binding with a wildcard address. | ||
| 1007 | */ | ||
| 1008 | if (!ep->base.bind_addr.port) { | ||
| 1009 | if (sctp_autobind(sk)) { | ||
| 1010 | err = -EAGAIN; | ||
| 1011 | goto out_free; | ||
| 1012 | } | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | scope = sctp_scope(&to); | ||
| 1016 | asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); | ||
| 1017 | if (!asoc) { | ||
| 1018 | err = -ENOMEM; | ||
| 1019 | goto out_free; | ||
| 1020 | } | ||
| 1021 | } | ||
| 1022 | |||
| 1023 | /* Prime the peer's transport structures. */ | ||
| 1024 | transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL, | ||
| 1025 | SCTP_UNKNOWN); | ||
| 1026 | if (!transport) { | ||
| 1027 | err = -ENOMEM; | ||
| 1028 | goto out_free; | ||
| 1029 | } | ||
| 1030 | |||
| 1031 | addrcnt++; | ||
| 1032 | addr_buf += af->sockaddr_len; | ||
| 1033 | walk_size += af->sockaddr_len; | ||
| 1034 | } | ||
| 1035 | |||
| 1036 | err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL); | ||
| 1037 | if (err < 0) { | ||
| 1038 | goto out_free; | ||
| 1039 | } | ||
| 1040 | |||
| 1041 | err = sctp_primitive_ASSOCIATE(asoc, NULL); | ||
| 1042 | if (err < 0) { | ||
| 1043 | goto out_free; | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | /* Initialize sk's dport and daddr for getpeername() */ | ||
| 1047 | inet_sk(sk)->dport = htons(asoc->peer.port); | ||
| 1048 | af = sctp_get_af_specific(to.sa.sa_family); | ||
| 1049 | af->to_sk_daddr(&to, sk); | ||
| 1050 | |||
| 1051 | timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK); | ||
| 1052 | err = sctp_wait_for_connect(asoc, &timeo); | ||
| 1053 | |||
| 1054 | /* Don't free association on exit. */ | ||
| 1055 | asoc = NULL; | ||
| 1056 | |||
| 1057 | out_free: | ||
| 1058 | |||
| 1059 | SCTP_DEBUG_PRINTK("About to exit __sctp_connect() free asoc: %p" | ||
| 1060 | " kaddrs: %p err: %d\n", | ||
| 1061 | asoc, kaddrs, err); | ||
| 1062 | if (asoc) | ||
| 1063 | sctp_association_free(asoc); | ||
| 1064 | return err; | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | /* Helper for tunneling sctp_connectx() requests through sctp_setsockopt() | ||
| 1068 | * | ||
| 1069 | * API 8.9 | ||
| 1070 | * int sctp_connectx(int sd, struct sockaddr *addrs, int addrcnt); | ||
| 1071 | * | ||
| 1072 | * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses. | ||
| 1073 | * If the sd is an IPv6 socket, the addresses passed can either be IPv4 | ||
| 1074 | * or IPv6 addresses. | ||
| 1075 | * | ||
| 1076 | * A single address may be specified as INADDR_ANY or IN6ADDR_ANY, see | ||
| 1077 | * Section 3.1.2 for this usage. | ||
| 1078 | * | ||
| 1079 | * addrs is a pointer to an array of one or more socket addresses. Each | ||
| 1080 | * address is contained in its appropriate structure (i.e. struct | ||
| 1081 | * sockaddr_in or struct sockaddr_in6) the family of the address type | ||
| 1082 | * must be used to distengish the address length (note that this | ||
| 1083 | * representation is termed a "packed array" of addresses). The caller | ||
| 1084 | * specifies the number of addresses in the array with addrcnt. | ||
| 1085 | * | ||
| 1086 | * On success, sctp_connectx() returns 0. On failure, sctp_connectx() returns | ||
| 1087 | * -1, and sets errno to the appropriate error code. | ||
| 1088 | * | ||
| 1089 | * For SCTP, the port given in each socket address must be the same, or | ||
| 1090 | * sctp_connectx() will fail, setting errno to EINVAL. | ||
| 1091 | * | ||
| 1092 | * An application can use sctp_connectx to initiate an association with | ||
| 1093 | * an endpoint that is multi-homed. Much like sctp_bindx() this call | ||
| 1094 | * allows a caller to specify multiple addresses at which a peer can be | ||
| 1095 | * reached. The way the SCTP stack uses the list of addresses to set up | ||
| 1096 | * the association is implementation dependant. This function only | ||
| 1097 | * specifies that the stack will try to make use of all the addresses in | ||
| 1098 | * the list when needed. | ||
| 1099 | * | ||
| 1100 | * Note that the list of addresses passed in is only used for setting up | ||
| 1101 | * the association. It does not necessarily equal the set of addresses | ||
| 1102 | * the peer uses for the resulting association. If the caller wants to | ||
| 1103 | * find out the set of peer addresses, it must use sctp_getpaddrs() to | ||
| 1104 | * retrieve them after the association has been set up. | ||
| 1105 | * | ||
| 1106 | * Basically do nothing but copying the addresses from user to kernel | ||
| 1107 | * land and invoking either sctp_connectx(). This is used for tunneling | ||
| 1108 | * the sctp_connectx() request through sctp_setsockopt() from userspace. | ||
| 1109 | * | ||
| 1110 | * We don't use copy_from_user() for optimization: we first do the | ||
| 1111 | * sanity checks (buffer size -fast- and access check-healthy | ||
| 1112 | * pointer); if all of those succeed, then we can alloc the memory | ||
| 1113 | * (expensive operation) needed to copy the data to kernel. Then we do | ||
| 1114 | * the copying without checking the user space area | ||
| 1115 | * (__copy_from_user()). | ||
| 1116 | * | ||
| 1117 | * On exit there is no need to do sockfd_put(), sys_setsockopt() does | ||
| 1118 | * it. | ||
| 1119 | * | ||
| 1120 | * sk The sk of the socket | ||
| 1121 | * addrs The pointer to the addresses in user land | ||
| 1122 | * addrssize Size of the addrs buffer | ||
| 1123 | * | ||
| 1124 | * Returns 0 if ok, <0 errno code on error. | ||
| 1125 | */ | ||
| 1126 | SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk, | ||
| 1127 | struct sockaddr __user *addrs, | ||
| 1128 | int addrs_size) | ||
| 1129 | { | ||
| 1130 | int err = 0; | ||
| 1131 | struct sockaddr *kaddrs; | ||
| 1132 | |||
| 1133 | SCTP_DEBUG_PRINTK("%s - sk %p addrs %p addrs_size %d\n", | ||
| 1134 | __FUNCTION__, sk, addrs, addrs_size); | ||
| 1135 | |||
| 1136 | if (unlikely(addrs_size <= 0)) | ||
| 1137 | return -EINVAL; | ||
| 1138 | |||
| 1139 | /* Check the user passed a healthy pointer. */ | ||
| 1140 | if (unlikely(!access_ok(VERIFY_READ, addrs, addrs_size))) | ||
| 1141 | return -EFAULT; | ||
| 1142 | |||
| 1143 | /* Alloc space for the address array in kernel memory. */ | ||
| 1144 | kaddrs = (struct sockaddr *)kmalloc(addrs_size, GFP_KERNEL); | ||
| 1145 | if (unlikely(!kaddrs)) | ||
| 1146 | return -ENOMEM; | ||
| 1147 | |||
| 1148 | if (__copy_from_user(kaddrs, addrs, addrs_size)) { | ||
| 1149 | err = -EFAULT; | ||
| 1150 | } else { | ||
| 1151 | err = __sctp_connect(sk, kaddrs, addrs_size); | ||
| 1152 | } | ||
| 1153 | |||
| 1154 | kfree(kaddrs); | ||
| 1155 | return err; | ||
| 1156 | } | ||
| 1157 | |||
| 916 | /* API 3.1.4 close() - UDP Style Syntax | 1158 | /* API 3.1.4 close() - UDP Style Syntax |
| 917 | * Applications use close() to perform graceful shutdown (as described in | 1159 | * Applications use close() to perform graceful shutdown (as described in |
| 918 | * Section 10.1 of [SCTP]) on ALL the associations currently represented | 1160 | * Section 10.1 of [SCTP]) on ALL the associations currently represented |
| @@ -1095,7 +1337,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 1095 | sp = sctp_sk(sk); | 1337 | sp = sctp_sk(sk); |
| 1096 | ep = sp->ep; | 1338 | ep = sp->ep; |
| 1097 | 1339 | ||
| 1098 | SCTP_DEBUG_PRINTK("Using endpoint: %s.\n", ep->debug_name); | 1340 | SCTP_DEBUG_PRINTK("Using endpoint: %p.\n", ep); |
| 1099 | 1341 | ||
| 1100 | /* We cannot send a message over a TCP-style listening socket. */ | 1342 | /* We cannot send a message over a TCP-style listening socket. */ |
| 1101 | if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) { | 1343 | if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) { |
| @@ -1306,7 +1548,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 1306 | } | 1548 | } |
| 1307 | 1549 | ||
| 1308 | /* Prime the peer's transport structures. */ | 1550 | /* Prime the peer's transport structures. */ |
| 1309 | transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL); | 1551 | transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL, SCTP_UNKNOWN); |
| 1310 | if (!transport) { | 1552 | if (!transport) { |
| 1311 | err = -ENOMEM; | 1553 | err = -ENOMEM; |
| 1312 | goto out_free; | 1554 | goto out_free; |
| @@ -2208,6 +2450,12 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname, | |||
| 2208 | optlen, SCTP_BINDX_REM_ADDR); | 2450 | optlen, SCTP_BINDX_REM_ADDR); |
| 2209 | break; | 2451 | break; |
| 2210 | 2452 | ||
| 2453 | case SCTP_SOCKOPT_CONNECTX: | ||
| 2454 | /* 'optlen' is the size of the addresses buffer. */ | ||
| 2455 | retval = sctp_setsockopt_connectx(sk, (struct sockaddr __user *)optval, | ||
| 2456 | optlen); | ||
| 2457 | break; | ||
| 2458 | |||
| 2211 | case SCTP_DISABLE_FRAGMENTS: | 2459 | case SCTP_DISABLE_FRAGMENTS: |
| 2212 | retval = sctp_setsockopt_disable_fragments(sk, optval, optlen); | 2460 | retval = sctp_setsockopt_disable_fragments(sk, optval, optlen); |
| 2213 | break; | 2461 | break; |
| @@ -2283,112 +2531,29 @@ out_nounlock: | |||
| 2283 | * | 2531 | * |
| 2284 | * len: the size of the address. | 2532 | * len: the size of the address. |
| 2285 | */ | 2533 | */ |
| 2286 | SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *uaddr, | 2534 | SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *addr, |
| 2287 | int addr_len) | 2535 | int addr_len) |
| 2288 | { | 2536 | { |
| 2289 | struct sctp_sock *sp; | ||
| 2290 | struct sctp_endpoint *ep; | ||
| 2291 | struct sctp_association *asoc; | ||
| 2292 | struct sctp_transport *transport; | ||
| 2293 | union sctp_addr to; | ||
| 2294 | struct sctp_af *af; | ||
| 2295 | sctp_scope_t scope; | ||
| 2296 | long timeo; | ||
| 2297 | int err = 0; | 2537 | int err = 0; |
| 2538 | struct sctp_af *af; | ||
| 2298 | 2539 | ||
| 2299 | sctp_lock_sock(sk); | 2540 | sctp_lock_sock(sk); |
| 2300 | 2541 | ||
| 2301 | SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d)\n", | 2542 | SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d\n", |
| 2302 | __FUNCTION__, sk, uaddr, addr_len); | 2543 | __FUNCTION__, sk, addr, addr_len); |
| 2303 | |||
| 2304 | sp = sctp_sk(sk); | ||
| 2305 | ep = sp->ep; | ||
| 2306 | |||
| 2307 | /* connect() cannot be done on a socket that is already in ESTABLISHED | ||
| 2308 | * state - UDP-style peeled off socket or a TCP-style socket that | ||
| 2309 | * is already connected. | ||
| 2310 | * It cannot be done even on a TCP-style listening socket. | ||
| 2311 | */ | ||
| 2312 | if (sctp_sstate(sk, ESTABLISHED) || | ||
| 2313 | (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) { | ||
| 2314 | err = -EISCONN; | ||
| 2315 | goto out_unlock; | ||
| 2316 | } | ||
| 2317 | |||
| 2318 | err = sctp_verify_addr(sk, (union sctp_addr *)uaddr, addr_len); | ||
| 2319 | if (err) | ||
| 2320 | goto out_unlock; | ||
| 2321 | |||
| 2322 | if (addr_len > sizeof(to)) | ||
| 2323 | addr_len = sizeof(to); | ||
| 2324 | memcpy(&to, uaddr, addr_len); | ||
| 2325 | to.v4.sin_port = ntohs(to.v4.sin_port); | ||
| 2326 | |||
| 2327 | asoc = sctp_endpoint_lookup_assoc(ep, &to, &transport); | ||
| 2328 | if (asoc) { | ||
| 2329 | if (asoc->state >= SCTP_STATE_ESTABLISHED) | ||
| 2330 | err = -EISCONN; | ||
| 2331 | else | ||
| 2332 | err = -EALREADY; | ||
| 2333 | goto out_unlock; | ||
| 2334 | } | ||
| 2335 | |||
| 2336 | /* If we could not find a matching association on the endpoint, | ||
| 2337 | * make sure that there is no peeled-off association matching the | ||
| 2338 | * peer address even on another socket. | ||
| 2339 | */ | ||
| 2340 | if (sctp_endpoint_is_peeled_off(ep, &to)) { | ||
| 2341 | err = -EADDRNOTAVAIL; | ||
| 2342 | goto out_unlock; | ||
| 2343 | } | ||
| 2344 | |||
| 2345 | /* If a bind() or sctp_bindx() is not called prior to a connect() | ||
| 2346 | * call, the system picks an ephemeral port and will choose an address | ||
| 2347 | * set equivalent to binding with a wildcard address. | ||
| 2348 | */ | ||
| 2349 | if (!ep->base.bind_addr.port) { | ||
| 2350 | if (sctp_autobind(sk)) { | ||
| 2351 | err = -EAGAIN; | ||
| 2352 | goto out_unlock; | ||
| 2353 | } | ||
| 2354 | } | ||
| 2355 | |||
| 2356 | scope = sctp_scope(&to); | ||
| 2357 | asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); | ||
| 2358 | if (!asoc) { | ||
| 2359 | err = -ENOMEM; | ||
| 2360 | goto out_unlock; | ||
| 2361 | } | ||
| 2362 | 2544 | ||
| 2363 | /* Prime the peer's transport structures. */ | 2545 | /* Validate addr_len before calling common connect/connectx routine. */ |
| 2364 | transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL); | 2546 | af = sctp_get_af_specific(addr->sa_family); |
| 2365 | if (!transport) { | 2547 | if (!af || addr_len < af->sockaddr_len) { |
| 2366 | sctp_association_free(asoc); | 2548 | err = -EINVAL; |
| 2367 | goto out_unlock; | 2549 | } else { |
| 2368 | } | 2550 | /* Pass correct addr len to common routine (so it knows there |
| 2369 | err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL); | 2551 | * is only one address being passed. |
| 2370 | if (err < 0) { | 2552 | */ |
| 2371 | sctp_association_free(asoc); | 2553 | err = __sctp_connect(sk, addr, af->sockaddr_len); |
| 2372 | goto out_unlock; | ||
| 2373 | } | ||
| 2374 | |||
| 2375 | err = sctp_primitive_ASSOCIATE(asoc, NULL); | ||
| 2376 | if (err < 0) { | ||
| 2377 | sctp_association_free(asoc); | ||
| 2378 | goto out_unlock; | ||
| 2379 | } | 2554 | } |
| 2380 | 2555 | ||
| 2381 | /* Initialize sk's dport and daddr for getpeername() */ | ||
| 2382 | inet_sk(sk)->dport = htons(asoc->peer.port); | ||
| 2383 | af = sctp_get_af_specific(to.sa.sa_family); | ||
| 2384 | af->to_sk_daddr(&to, sk); | ||
| 2385 | |||
| 2386 | timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK); | ||
| 2387 | err = sctp_wait_for_connect(asoc, &timeo); | ||
| 2388 | |||
| 2389 | out_unlock: | ||
| 2390 | sctp_release_sock(sk); | 2556 | sctp_release_sock(sk); |
| 2391 | |||
| 2392 | return err; | 2557 | return err; |
| 2393 | } | 2558 | } |
| 2394 | 2559 | ||
| @@ -2677,12 +2842,15 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, | |||
| 2677 | /* Map ipv4 address into v4-mapped-on-v6 address. */ | 2842 | /* Map ipv4 address into v4-mapped-on-v6 address. */ |
| 2678 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), | 2843 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), |
| 2679 | (union sctp_addr *)&status.sstat_primary.spinfo_address); | 2844 | (union sctp_addr *)&status.sstat_primary.spinfo_address); |
| 2680 | status.sstat_primary.spinfo_state = transport->active; | 2845 | status.sstat_primary.spinfo_state = transport->state; |
| 2681 | status.sstat_primary.spinfo_cwnd = transport->cwnd; | 2846 | status.sstat_primary.spinfo_cwnd = transport->cwnd; |
| 2682 | status.sstat_primary.spinfo_srtt = transport->srtt; | 2847 | status.sstat_primary.spinfo_srtt = transport->srtt; |
| 2683 | status.sstat_primary.spinfo_rto = jiffies_to_msecs(transport->rto); | 2848 | status.sstat_primary.spinfo_rto = jiffies_to_msecs(transport->rto); |
| 2684 | status.sstat_primary.spinfo_mtu = transport->pmtu; | 2849 | status.sstat_primary.spinfo_mtu = transport->pmtu; |
| 2685 | 2850 | ||
| 2851 | if (status.sstat_primary.spinfo_state == SCTP_UNKNOWN) | ||
| 2852 | status.sstat_primary.spinfo_state = SCTP_ACTIVE; | ||
| 2853 | |||
| 2686 | if (put_user(len, optlen)) { | 2854 | if (put_user(len, optlen)) { |
| 2687 | retval = -EFAULT; | 2855 | retval = -EFAULT; |
| 2688 | goto out; | 2856 | goto out; |
| @@ -2733,12 +2901,15 @@ static int sctp_getsockopt_peer_addr_info(struct sock *sk, int len, | |||
| 2733 | return -EINVAL; | 2901 | return -EINVAL; |
| 2734 | 2902 | ||
| 2735 | pinfo.spinfo_assoc_id = sctp_assoc2id(transport->asoc); | 2903 | pinfo.spinfo_assoc_id = sctp_assoc2id(transport->asoc); |
| 2736 | pinfo.spinfo_state = transport->active; | 2904 | pinfo.spinfo_state = transport->state; |
| 2737 | pinfo.spinfo_cwnd = transport->cwnd; | 2905 | pinfo.spinfo_cwnd = transport->cwnd; |
| 2738 | pinfo.spinfo_srtt = transport->srtt; | 2906 | pinfo.spinfo_srtt = transport->srtt; |
| 2739 | pinfo.spinfo_rto = jiffies_to_msecs(transport->rto); | 2907 | pinfo.spinfo_rto = jiffies_to_msecs(transport->rto); |
| 2740 | pinfo.spinfo_mtu = transport->pmtu; | 2908 | pinfo.spinfo_mtu = transport->pmtu; |
| 2741 | 2909 | ||
| 2910 | if (pinfo.spinfo_state == SCTP_UNKNOWN) | ||
| 2911 | pinfo.spinfo_state = SCTP_ACTIVE; | ||
| 2912 | |||
| 2742 | if (put_user(len, optlen)) { | 2913 | if (put_user(len, optlen)) { |
| 2743 | retval = -EFAULT; | 2914 | retval = -EFAULT; |
| 2744 | goto out; | 2915 | goto out; |
| @@ -3591,7 +3762,8 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
| 3591 | int retval = 0; | 3762 | int retval = 0; |
| 3592 | int len; | 3763 | int len; |
| 3593 | 3764 | ||
| 3594 | SCTP_DEBUG_PRINTK("sctp_getsockopt(sk: %p, ...)\n", sk); | 3765 | SCTP_DEBUG_PRINTK("sctp_getsockopt(sk: %p... optname: %d)\n", |
| 3766 | sk, optname); | ||
| 3595 | 3767 | ||
| 3596 | /* I can hardly begin to describe how wrong this is. This is | 3768 | /* I can hardly begin to describe how wrong this is. This is |
| 3597 | * so broken as to be worse than useless. The API draft | 3769 | * so broken as to be worse than useless. The API draft |
| @@ -4596,8 +4768,7 @@ out: | |||
| 4596 | return err; | 4768 | return err; |
| 4597 | 4769 | ||
| 4598 | do_error: | 4770 | do_error: |
| 4599 | if (asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1 >= | 4771 | if (asoc->init_err_counter + 1 >= asoc->max_init_attempts) |
| 4600 | asoc->max_init_attempts) | ||
| 4601 | err = -ETIMEDOUT; | 4772 | err = -ETIMEDOUT; |
| 4602 | else | 4773 | else |
| 4603 | err = -ECONNREFUSED; | 4774 | err = -ECONNREFUSED; |
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index f30882e1e96a..0ec0fde6e6c5 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
| @@ -83,7 +83,9 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, | |||
| 83 | peer->last_time_used = jiffies; | 83 | peer->last_time_used = jiffies; |
| 84 | peer->last_time_ecne_reduced = jiffies; | 84 | peer->last_time_ecne_reduced = jiffies; |
| 85 | 85 | ||
| 86 | peer->active = SCTP_ACTIVE; | 86 | peer->init_sent_count = 0; |
| 87 | |||
| 88 | peer->state = SCTP_ACTIVE; | ||
| 87 | peer->hb_allowed = 0; | 89 | peer->hb_allowed = 0; |
| 88 | 90 | ||
| 89 | /* Initialize the default path max_retrans. */ | 91 | /* Initialize the default path max_retrans. */ |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 0a4260719a12..d65ed8684fc1 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
| @@ -118,7 +118,6 @@ retry: | |||
| 118 | xfrm_policy_put_afinfo(afinfo); | 118 | xfrm_policy_put_afinfo(afinfo); |
| 119 | return type; | 119 | return type; |
| 120 | } | 120 | } |
| 121 | EXPORT_SYMBOL(xfrm_get_type); | ||
| 122 | 121 | ||
| 123 | int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, | 122 | int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, |
| 124 | unsigned short family) | 123 | unsigned short family) |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 2537f26f097c..9d206c282cf1 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
| @@ -1055,6 +1055,43 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu) | |||
| 1055 | } | 1055 | } |
| 1056 | 1056 | ||
| 1057 | EXPORT_SYMBOL(xfrm_state_mtu); | 1057 | EXPORT_SYMBOL(xfrm_state_mtu); |
| 1058 | |||
| 1059 | int xfrm_init_state(struct xfrm_state *x) | ||
| 1060 | { | ||
| 1061 | struct xfrm_state_afinfo *afinfo; | ||
| 1062 | int family = x->props.family; | ||
| 1063 | int err; | ||
| 1064 | |||
| 1065 | err = -EAFNOSUPPORT; | ||
| 1066 | afinfo = xfrm_state_get_afinfo(family); | ||
| 1067 | if (!afinfo) | ||
| 1068 | goto error; | ||
| 1069 | |||
| 1070 | err = 0; | ||
| 1071 | if (afinfo->init_flags) | ||
| 1072 | err = afinfo->init_flags(x); | ||
| 1073 | |||
| 1074 | xfrm_state_put_afinfo(afinfo); | ||
| 1075 | |||
| 1076 | if (err) | ||
| 1077 | goto error; | ||
| 1078 | |||
| 1079 | err = -EPROTONOSUPPORT; | ||
| 1080 | x->type = xfrm_get_type(x->id.proto, family); | ||
| 1081 | if (x->type == NULL) | ||
| 1082 | goto error; | ||
| 1083 | |||
| 1084 | err = x->type->init_state(x); | ||
| 1085 | if (err) | ||
| 1086 | goto error; | ||
| 1087 | |||
| 1088 | x->km.state = XFRM_STATE_VALID; | ||
| 1089 | |||
| 1090 | error: | ||
| 1091 | return err; | ||
| 1092 | } | ||
| 1093 | |||
| 1094 | EXPORT_SYMBOL(xfrm_init_state); | ||
| 1058 | 1095 | ||
| 1059 | void __init xfrm_state_init(void) | 1096 | void __init xfrm_state_init(void) |
| 1060 | { | 1097 | { |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 5ce8558eac91..ecade4893a13 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
| @@ -249,17 +249,10 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p, | |||
| 249 | if ((err = attach_encap_tmpl(&x->encap, xfrma[XFRMA_ENCAP-1]))) | 249 | if ((err = attach_encap_tmpl(&x->encap, xfrma[XFRMA_ENCAP-1]))) |
| 250 | goto error; | 250 | goto error; |
| 251 | 251 | ||
| 252 | err = -ENOENT; | 252 | err = xfrm_init_state(x); |
| 253 | x->type = xfrm_get_type(x->id.proto, x->props.family); | ||
| 254 | if (x->type == NULL) | ||
| 255 | goto error; | ||
| 256 | |||
| 257 | err = x->type->init_state(x, NULL); | ||
| 258 | if (err) | 253 | if (err) |
| 259 | goto error; | 254 | goto error; |
| 260 | 255 | ||
| 261 | x->curlft.add_time = (unsigned long) xtime.tv_sec; | ||
| 262 | x->km.state = XFRM_STATE_VALID; | ||
| 263 | x->km.seq = p->seq; | 256 | x->km.seq = p->seq; |
| 264 | 257 | ||
| 265 | return x; | 258 | return x; |
