]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/dccp/options.c
Pull kmalloc into release branch
[linux-2.6-omap-h63xx.git] / net / dccp / options.c
index 0161a18e739a3629f8775f634adac92aece87894..c3cda1e39aa8ccc500e4e7a36b0e72679d94a8ed 100644 (file)
@@ -11,7 +11,6 @@
  *      as published by the Free Software Foundation; either version
  *      2 of the License, or (at your option) any later version.
  */
-#include <linux/config.h>
 #include <linux/dccp.h>
 #include <linux/module.h>
 #include <linux/types.h>
@@ -30,14 +29,14 @@ int dccp_feat_default_ack_ratio           = DCCPF_INITIAL_ACK_RATIO;
 int dccp_feat_default_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR;
 int dccp_feat_default_send_ndp_count  = DCCPF_INITIAL_SEND_NDP_COUNT;
 
-void dccp_options_init(struct dccp_options *dccpo)
+void dccp_minisock_init(struct dccp_minisock *dmsk)
 {
-       dccpo->dccpo_sequence_window = dccp_feat_default_sequence_window;
-       dccpo->dccpo_rx_ccid         = dccp_feat_default_rx_ccid;
-       dccpo->dccpo_tx_ccid         = dccp_feat_default_tx_ccid;
-       dccpo->dccpo_ack_ratio       = dccp_feat_default_ack_ratio;
-       dccpo->dccpo_send_ack_vector = dccp_feat_default_send_ack_vector;
-       dccpo->dccpo_send_ndp_count  = dccp_feat_default_send_ndp_count;
+       dmsk->dccpms_sequence_window = dccp_feat_default_sequence_window;
+       dmsk->dccpms_rx_ccid         = dccp_feat_default_rx_ccid;
+       dmsk->dccpms_tx_ccid         = dccp_feat_default_tx_ccid;
+       dmsk->dccpms_ack_ratio       = dccp_feat_default_ack_ratio;
+       dmsk->dccpms_send_ack_vector = dccp_feat_default_send_ack_vector;
+       dmsk->dccpms_send_ndp_count  = dccp_feat_default_send_ndp_count;
 }
 
 static u32 dccp_decode_value_var(const unsigned char *bf, const u8 len)
@@ -78,6 +77,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
 
        memset(opt_recv, 0, sizeof(*opt_recv));
 
+       opt = len = 0;
        while (opt_ptr != opt_end) {
                opt   = *opt_ptr++;
                len   = 0;
@@ -150,7 +150,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
                        if (pkt_type == DCCP_PKT_DATA)
                                break;
 
-                       if (dp->dccps_options.dccpo_send_ack_vector &&
+                       if (dccp_msk(sk)->dccpms_send_ack_vector &&
                            dccp_ackvec_parse(sk, skb, opt, value, len))
                                goto out_invalid_option;
                        break;
@@ -283,17 +283,14 @@ static inline int dccp_ndp_len(const int ndp)
        return likely(ndp <= 0xFF) ? 1 : ndp <= 0xFFFF ? 2 : 3;
 }
 
-void dccp_insert_option(struct sock *sk, struct sk_buff *skb,
+int dccp_insert_option(struct sock *sk, struct sk_buff *skb,
                        const unsigned char option,
                        const void *value, const unsigned char len)
 {
        unsigned char *to;
 
-       if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 2 > DCCP_MAX_OPT_LEN) {
-               LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to insert "
-                              "%d option!\n", option);
-               return;
-       }
+       if (DCCP_SKB_CB(skb)->dccpd_opt_len + len + 2 > DCCP_MAX_OPT_LEN)
+               return -1;
 
        DCCP_SKB_CB(skb)->dccpd_opt_len += len + 2;
 
@@ -302,11 +299,12 @@ void dccp_insert_option(struct sock *sk, struct sk_buff *skb,
        *to++ = len + 2;
 
        memcpy(to, value, len);
+       return 0;
 }
 
 EXPORT_SYMBOL_GPL(dccp_insert_option);
 
-static void dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb)
+static int dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb)
 {
        struct dccp_sock *dp = dccp_sk(sk);
        int ndp = dp->dccps_ndp_count;
@@ -322,7 +320,7 @@ static void dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb)
                const int len = ndp_len + 2;
 
                if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
-                       return;
+                       return -1;
 
                DCCP_SKB_CB(skb)->dccpd_opt_len += len;
 
@@ -331,6 +329,8 @@ static void dccp_insert_option_ndp(struct sock *sk, struct sk_buff *skb)
                *ptr++ = len;
                dccp_encode_value_var(ndp, ptr, ndp_len);
        }
+
+       return 0;
 }
 
 static inline int dccp_elapsed_time_len(const u32 elapsed_time)
@@ -338,27 +338,18 @@ static inline int dccp_elapsed_time_len(const u32 elapsed_time)
        return elapsed_time == 0 ? 0 : elapsed_time <= 0xFFFF ? 2 : 4;
 }
 
-void dccp_insert_option_elapsed_time(struct sock *sk,
-                                    struct sk_buff *skb,
-                                    u32 elapsed_time)
+int dccp_insert_option_elapsed_time(struct sock *sk, struct sk_buff *skb,
+                                   u32 elapsed_time)
 {
-#ifdef CONFIG_IP_DCCP_DEBUG
-       struct dccp_sock *dp = dccp_sk(sk);
-       const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
-                                       "CLIENT TX opt: " : "server TX opt: ";
-#endif
        const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
        const int len = 2 + elapsed_time_len;
        unsigned char *to;
 
        if (elapsed_time_len == 0)
-               return;
+               return 0;
 
-       if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) {
-               LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to "
-                                        "insert elapsed time!\n");
-               return;
-       }
+       if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
+               return -1;
 
        DCCP_SKB_CB(skb)->dccpd_opt_len += len;
 
@@ -374,10 +365,7 @@ void dccp_insert_option_elapsed_time(struct sock *sk,
                memcpy(to, &var32, 4);
        }
 
-       dccp_pr_debug("%sELAPSED_TIME=%u, len=%d, seqno=%llu\n",
-                     debug_prefix, elapsed_time,
-                     len,
-                     (unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq);
+       return 0;
 }
 
 EXPORT_SYMBOL_GPL(dccp_insert_option_elapsed_time);
@@ -398,7 +386,7 @@ void dccp_timestamp(const struct sock *sk, struct timeval *tv)
 
 EXPORT_SYMBOL_GPL(dccp_timestamp);
 
-void dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb)
+int dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb)
 {
        struct timeval tv;
        __be32 now;
@@ -408,19 +396,15 @@ void dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb)
        /* yes this will overflow but that is the point as we want a
         * 10 usec 32 bit timer which mean it wraps every 11.9 hours */
 
-       dccp_insert_option(sk, skb, DCCPO_TIMESTAMP, &now, sizeof(now));
+       return dccp_insert_option(sk, skb, DCCPO_TIMESTAMP, &now, sizeof(now));
 }
 
 EXPORT_SYMBOL_GPL(dccp_insert_option_timestamp);
 
-static void dccp_insert_option_timestamp_echo(struct sock *sk,
-                                             struct sk_buff *skb)
+static int dccp_insert_option_timestamp_echo(struct sock *sk,
+                                            struct sk_buff *skb)
 {
        struct dccp_sock *dp = dccp_sk(sk);
-#ifdef CONFIG_IP_DCCP_DEBUG
-       const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ?
-                                       "CLIENT TX opt: " : "server TX opt: ";
-#endif
        struct timeval now;
        __be32 tstamp_echo;
        u32 elapsed_time;
@@ -432,11 +416,8 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk,
        elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
        len = 6 + elapsed_time_len;
 
-       if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) {
-               LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to insert "
-                                        "timestamp echo!\n");
-               return;
-       }
+       if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN)
+               return -1;
 
        DCCP_SKB_CB(skb)->dccpd_opt_len += len;
 
@@ -456,14 +437,10 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk,
                memcpy(to, &var32, 4);
        }
 
-       dccp_pr_debug("%sTIMESTAMP_ECHO=%u, len=%d, seqno=%llu\n",
-                     debug_prefix, dp->dccps_timestamp_echo,
-                     len,
-                     (unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq);
-
        dp->dccps_timestamp_echo = 0;
        dp->dccps_timestamp_time.tv_sec = 0;
        dp->dccps_timestamp_time.tv_usec = 0;
+       return 0;
 }
 
 static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat,
@@ -491,15 +468,15 @@ static int dccp_insert_feat_opt(struct sk_buff *skb, u8 type, u8 feat,
        return 0;
 }
 
-static void dccp_insert_feat(struct sock *sk, struct sk_buff *skb)
+static int dccp_insert_options_feat(struct sock *sk, struct sk_buff *skb)
 {
        struct dccp_sock *dp = dccp_sk(sk);
+       struct dccp_minisock *dmsk = dccp_msk(sk);
        struct dccp_opt_pend *opt, *next;
        int change = 0;
 
        /* confirm any options [NN opts] */
-       list_for_each_entry_safe(opt, next, &dp->dccps_options.dccpo_conf,
-                                dccpop_node) {
+       list_for_each_entry_safe(opt, next, &dmsk->dccpms_conf, dccpop_node) {
                dccp_insert_feat_opt(skb, opt->dccpop_type,
                                     opt->dccpop_feat, opt->dccpop_val,
                                     opt->dccpop_len);
@@ -508,11 +485,10 @@ static void dccp_insert_feat(struct sock *sk, struct sk_buff *skb)
                        kfree(opt->dccpop_val);
                kfree(opt);
        }
-       INIT_LIST_HEAD(&dp->dccps_options.dccpo_conf);
+       INIT_LIST_HEAD(&dmsk->dccpms_conf);
 
        /* see which features we need to send */
-       list_for_each_entry(opt, &dp->dccps_options.dccpo_pending,
-                           dccpop_node) {
+       list_for_each_entry(opt, &dmsk->dccpms_pending, dccpop_node) {
                /* see if we need to send any confirm */
                if (opt->dccpop_sc) {
                        dccp_insert_feat_opt(skb, opt->dccpop_type + 1,
@@ -551,44 +527,49 @@ static void dccp_insert_feat(struct sock *sk, struct sk_buff *skb)
                inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
                                          inet_csk(sk)->icsk_rto, DCCP_RTO_MAX);
        }
+
+       return 0;
 }
 
-void dccp_insert_options(struct sock *sk, struct sk_buff *skb)
+int dccp_insert_options(struct sock *sk, struct sk_buff *skb)
 {
        struct dccp_sock *dp = dccp_sk(sk);
+       struct dccp_minisock *dmsk = dccp_msk(sk);
 
        DCCP_SKB_CB(skb)->dccpd_opt_len = 0;
 
-       if (dp->dccps_options.dccpo_send_ndp_count)
-               dccp_insert_option_ndp(sk, skb);
+       if (dmsk->dccpms_send_ndp_count &&
+           dccp_insert_option_ndp(sk, skb))
+               return -1;
 
        if (!dccp_packet_without_ack(skb)) {
-               if (dp->dccps_options.dccpo_send_ack_vector &&
-                   dccp_ackvec_pending(dp->dccps_hc_rx_ackvec))
-                       dccp_insert_option_ackvec(sk, skb);
-               if (dp->dccps_timestamp_echo != 0)
-                       dccp_insert_option_timestamp_echo(sk, skb);
+               if (dmsk->dccpms_send_ack_vector &&
+                   dccp_ackvec_pending(dp->dccps_hc_rx_ackvec) &&
+                   dccp_insert_option_ackvec(sk, skb))
+                       return -1;
+
+               if (dp->dccps_timestamp_echo != 0 &&
+                   dccp_insert_option_timestamp_echo(sk, skb))
+                       return -1;
        }
 
        if (dp->dccps_hc_rx_insert_options) {
-               ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb);
+               if (ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb))
+                       return -1;
                dp->dccps_hc_rx_insert_options = 0;
        }
        if (dp->dccps_hc_tx_insert_options) {
-               ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb);
+               if (ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb))
+                       return -1;
                dp->dccps_hc_tx_insert_options = 0;
        }
 
        /* Feature negotiation */
-       switch(DCCP_SKB_CB(skb)->dccpd_type) {
-               /* Data packets can't do feat negotiation */
-       case DCCP_PKT_DATA:
-       case DCCP_PKT_DATAACK:
-               break;
-       default:
-               dccp_insert_feat(sk, skb);
-               break;
-       }
+       /* Data packets can't do feat negotiation */
+       if (DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATA &&
+           DCCP_SKB_CB(skb)->dccpd_type != DCCP_PKT_DATAACK &&
+           dccp_insert_options_feat(sk, skb))
+               return -1;
 
        /* XXX: insert other options when appropriate */
 
@@ -602,4 +583,6 @@ void dccp_insert_options(struct sock *sk, struct sk_buff *skb)
                        DCCP_SKB_CB(skb)->dccpd_opt_len += padding;
                }
        }
+
+       return 0;
 }