Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ac75773c authored by Gerrit Renker's avatar Gerrit Renker Committed by David S. Miller
Browse files

dccp: Per-socket initialisation of feature negotiation



This provides feature-negotiation initialisation for both DCCP sockets
and DCCP request_sockets, to support feature negotiation during
connection setup.

It also resolves a FIXME regarding the congestion control
initialisation.

Thanks to Wei Yongjun for help with the IPv6 side of this patch.

Signed-off-by: default avatarGerrit Renker <gerrit@erg.abdn.ac.uk>
Acked-by: default avatarIan McDonald <ian.mcdonald@jandi.co.nz>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 61e6473e
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -412,6 +412,7 @@ extern void dccp_minisock_init(struct dccp_minisock *dmsk);
 * @dreq_iss: initial sequence number sent on the Response (RFC 4340, 7.1)
 * @dreq_iss: initial sequence number sent on the Response (RFC 4340, 7.1)
 * @dreq_isr: initial sequence number received on the Request
 * @dreq_isr: initial sequence number received on the Request
 * @dreq_service: service code present on the Request (there is just one)
 * @dreq_service: service code present on the Request (there is just one)
 * @dreq_featneg: feature negotiation options for this connection
 * The following two fields are analogous to the ones in dccp_sock:
 * The following two fields are analogous to the ones in dccp_sock:
 * @dreq_timestamp_echo: last received timestamp to echo (13.1)
 * @dreq_timestamp_echo: last received timestamp to echo (13.1)
 * @dreq_timestamp_echo: the time of receiving the last @dreq_timestamp_echo
 * @dreq_timestamp_echo: the time of receiving the last @dreq_timestamp_echo
@@ -421,6 +422,7 @@ struct dccp_request_sock {
	__u64			 dreq_iss;
	__u64			 dreq_iss;
	__u64			 dreq_isr;
	__u64			 dreq_isr;
	__be32			 dreq_service;
	__be32			 dreq_service;
	struct list_head	 dreq_featneg;
	__u32			 dreq_timestamp_echo;
	__u32			 dreq_timestamp_echo;
	__u32			 dreq_timestamp_time;
	__u32			 dreq_timestamp_time;
};
};
@@ -498,6 +500,7 @@ struct dccp_ackvec;
 * @dccps_mss_cache - current value of MSS (path MTU minus header sizes)
 * @dccps_mss_cache - current value of MSS (path MTU minus header sizes)
 * @dccps_rate_last - timestamp for rate-limiting DCCP-Sync (RFC 4340, 7.5.4)
 * @dccps_rate_last - timestamp for rate-limiting DCCP-Sync (RFC 4340, 7.5.4)
 * @dccps_minisock - associated minisock (accessed via dccp_msk)
 * @dccps_minisock - associated minisock (accessed via dccp_msk)
 * @dccps_featneg - tracks feature-negotiation state (mostly during handshake)
 * @dccps_hc_rx_ackvec - rx half connection ack vector
 * @dccps_hc_rx_ackvec - rx half connection ack vector
 * @dccps_hc_rx_ccid - CCID used for the receiver (or receiving half-connection)
 * @dccps_hc_rx_ccid - CCID used for the receiver (or receiving half-connection)
 * @dccps_hc_tx_ccid - CCID used for the sender (or sending half-connection)
 * @dccps_hc_tx_ccid - CCID used for the sender (or sending half-connection)
@@ -535,6 +538,7 @@ struct dccp_sock {
	__u64				dccps_ndp_count:48;
	__u64				dccps_ndp_count:48;
	unsigned long			dccps_rate_last;
	unsigned long			dccps_rate_last;
	struct dccp_minisock		dccps_minisock;
	struct dccp_minisock		dccps_minisock;
	struct list_head		dccps_featneg;
	struct dccp_ackvec		*dccps_hc_rx_ackvec;
	struct dccp_ackvec		*dccps_hc_rx_ackvec;
	struct ccid			*dccps_hc_rx_ccid;
	struct ccid			*dccps_hc_rx_ccid;
	struct ccid			*dccps_hc_tx_ccid;
	struct ccid			*dccps_hc_tx_ccid;
+2 −1
Original line number Original line Diff line number Diff line
@@ -252,7 +252,8 @@ extern const char *dccp_state_name(const int state);
extern void dccp_set_state(struct sock *sk, const int state);
extern void dccp_set_state(struct sock *sk, const int state);
extern void dccp_done(struct sock *sk);
extern void dccp_done(struct sock *sk);


extern void dccp_reqsk_init(struct request_sock *req, struct sk_buff *skb);
extern int  dccp_reqsk_init(struct request_sock *rq, struct dccp_sock const *dp,
			    struct sk_buff const *skb);


extern int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb);
extern int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb);


+55 −0
Original line number Original line Diff line number Diff line
@@ -90,6 +90,20 @@ static u8 dccp_feat_type(u8 feat_num)
	return dccp_feat_table[idx].reconciliation;
	return dccp_feat_table[idx].reconciliation;
}
}


/* copy constructor, fval must not already contain allocated memory */
static int dccp_feat_clone_sp_val(dccp_feat_val *fval, u8 const *val, u8 len)
{
	fval->sp.len = len;
	if (fval->sp.len > 0) {
		fval->sp.vec = kmemdup(val, len, gfp_any());
		if (fval->sp.vec == NULL) {
			fval->sp.len = 0;
			return -ENOBUFS;
		}
	}
	return 0;
}

static void dccp_feat_val_destructor(u8 feat_num, dccp_feat_val *val)
static void dccp_feat_val_destructor(u8 feat_num, dccp_feat_val *val)
{
{
	if (unlikely(val == NULL))
	if (unlikely(val == NULL))
@@ -99,6 +113,28 @@ static void dccp_feat_val_destructor(u8 feat_num, dccp_feat_val *val)
	memset(val, 0, sizeof(*val));
	memset(val, 0, sizeof(*val));
}
}


static struct dccp_feat_entry *
	      dccp_feat_clone_entry(struct dccp_feat_entry const *original)
{
	struct dccp_feat_entry *new;
	u8 type = dccp_feat_type(original->feat_num);

	if (type == FEAT_UNKNOWN)
		return NULL;

	new = kmemdup(original, sizeof(struct dccp_feat_entry), gfp_any());
	if (new == NULL)
		return NULL;

	if (type == FEAT_SP && dccp_feat_clone_sp_val(&new->val,
						      original->val.sp.vec,
						      original->val.sp.len)) {
		kfree(new);
		return NULL;
	}
	return new;
}

static void dccp_feat_entry_destructor(struct dccp_feat_entry *entry)
static void dccp_feat_entry_destructor(struct dccp_feat_entry *entry)
{
{
	if (entry != NULL) {
	if (entry != NULL) {
@@ -133,6 +169,25 @@ void dccp_feat_list_purge(struct list_head *fn_list)
}
}
EXPORT_SYMBOL_GPL(dccp_feat_list_purge);
EXPORT_SYMBOL_GPL(dccp_feat_list_purge);


/* generate @to as full clone of @from - @to must not contain any nodes */
int dccp_feat_clone_list(struct list_head const *from, struct list_head *to)
{
	struct dccp_feat_entry *entry, *new;

	INIT_LIST_HEAD(to);
	list_for_each_entry(entry, from, node) {
		new = dccp_feat_clone_entry(entry);
		if (new == NULL)
			goto cloning_failed;
		list_add_tail(&new->node, to);
	}
	return 0;

cloning_failed:
	dccp_feat_list_purge(to);
	return -ENOMEM;
}

int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature,
int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature,
		     u8 *val, u8 len, gfp_t gfp)
		     u8 *val, u8 len, gfp_t gfp)
{
{
+1 −0
Original line number Original line Diff line number Diff line
@@ -96,6 +96,7 @@ extern int dccp_feat_confirm_recv(struct sock *sk, u8 type, u8 feature,
				   u8 *val, u8 len);
				   u8 *val, u8 len);
extern void dccp_feat_clean(struct dccp_minisock *dmsk);
extern void dccp_feat_clean(struct dccp_minisock *dmsk);
extern int  dccp_feat_clone(struct sock *oldsk, struct sock *newsk);
extern int  dccp_feat_clone(struct sock *oldsk, struct sock *newsk);
extern int  dccp_feat_clone_list(struct list_head const *, struct list_head *);
extern int  dccp_feat_init(struct dccp_minisock *dmsk);
extern int  dccp_feat_init(struct dccp_minisock *dmsk);


#endif /* _DCCP_FEAT_H */
#endif /* _DCCP_FEAT_H */
+0 −2
Original line number Original line Diff line number Diff line
@@ -590,8 +590,6 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
			if (inet_csk(sk)->icsk_af_ops->conn_request(sk,
			if (inet_csk(sk)->icsk_af_ops->conn_request(sk,
								    skb) < 0)
								    skb) < 0)
				return 1;
				return 1;

			/* FIXME: do congestion control initialization */
			goto discard;
			goto discard;
		}
		}
		if (dh->dccph_type == DCCP_PKT_RESET)
		if (dh->dccph_type == DCCP_PKT_RESET)
Loading