⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dcp.c

📁 DCCP协议在linux下的C编程实现 linux C
💻 C
📖 第 1 页 / 共 5 页
字号:
 * Parameters:	tp - the DCCP-related information for the sending socket * 		type - the option number that is being confirmed * 		val - the value for the confirmed option */static inline void genanswer (struct dcp_opt *tp, unsigned char type, unsigned char val){	if (tp->opt_a_sz + 4 > DCP_OPTASZ)		return;	tp->opt_append[tp->opt_a_sz++] = DCP_OPT_ANSWER;			tp->opt_append[tp->opt_a_sz++] = 4;	tp->opt_append[tp->opt_a_sz++] = type;	tp->opt_append[tp->opt_a_sz++] = val;	return;}/* Generates a DCCP Choose option, i.e a prefer option, and adds it to the list of options to be included in the next outgoing packet * * Parameters: 	tp - the DCCP-related information for the sending socket * 		type - the option number that we are stating our preferences for * 		val - the prefered value for the option */// NOTE: It appears that we only allow a single preferred value - this is not in line with the protocol specs. We should support multiple// values.static inline void genchoose (struct dcp_opt *tp, unsigned char type, unsigned char val){	if (tp->opt_a_sz + 4 > DCP_OPTASZ)		return;	tp->opt_append[tp->opt_a_sz++] = DCP_OPT_CHOOSE;	tp->opt_append[tp->opt_a_sz++] = 4;	tp->opt_append[tp->opt_a_sz++] = type;	tp->opt_append[tp->opt_a_sz++] = val;	return;}/* Parses and deals with the options that follow the generic packet header * * Parameters:	skb - the sk_buff containing the received packet * 		sk - the socket relating to the outgoing connection which will respond to the packet */static void generic_option_parse (struct sk_buff *skb, struct sock *sk){	unsigned char *p, *eop, *b, *t,g;	struct dcp_opt *tp = &(sk->tp_pinfo.tp_dcp);	if (skb->len < 16) return; 	// start of the options field	p = skb->data + optionoffset (skb->data[4]);	// end of the options field	b =  skb->data + (skb->data[8] * 4); //IS THIS A BUFFER OVERFLOW??	//This is a snaeky place to put it.	while ( p < b)	{		// padding and discard options only take up a single byte		if (*p < 32)			eop = p+1;		else		{			// making sure that the option does not go past the end of the packet			if (!( ((p+1) - skb->data) < skb->len))				break;			eop = p + p[1];			if ((eop - skb->data) > skb->len)				break;		}		switch (*p)		{			case DCP_OPT_PAD:			case DCP_OPT_DISCARD:			case DCP_OPT_IGNORED:			case DCP_OPT_ICOOKIE:			case DCP_OPT_ACKV0:			case DCP_OPT_ACKV1:			case DCP_OPT_RBDROP:			case DCP_OPT_TS_ECHO:			case DCP_OPT_MOBILE:			case DCP_OPT_BCD:				break;		/* essentially ignore because we're handled other places */			case  DCP_OPT_WINCOUNT:  /* CCID 3 specific */				if ((eop - p) == 3)				{				}				break;			case DCP_OPT_LOSSEVENT: /* CCID 3 specific */				if ((eop - p) == 6)				{					tp->losseventrate = ntohl((u32) *(p+2)); //is this right?				}				break;			case  DCP_OPT_TS: /* Timestamp */				if ((eop - p) == 6) // if statements like this are simple length checking				{					// copying the timestamp so that we can echo it back on the next packet					tp->ts_r_stamp = jiffies;					memcpy (&tp->ts_r,p+2,4);				}				break;			case DCP_OPT_ASK: /* If we see this, then we are being asked to change the value of a feature at this location */				if ((eop-p)>=4)					switch (p[2])					{						case DCP_NEG_TYPE_CC: /* Congestion control negotiation */							g = 0;							if (!(tp->negibuf & 0x01))							{								// This for loop is a bit shoddy. Without braces, only the first value for CCID in the								// ASK option will be used. With braces, only the last value will be used.								// POSSIBLE FIX: replace current for statement with - for (t = p+3; t < eop && g == 0; t++) and								// insert braces around loop. Close brace needs to be placed before if (!g).								//								// FIXED - SHANE								for (t = p+3; t< eop && g == 0;t++) {																		if (*t == 2)									{#if DCP_DEBUG > 1										printk ("%d: responding to ask ccid 2 by setting ccid and generating answer\n",tp->whoami);#endif										tp->ccid = 2;										genanswer (tp,DCP_NEG_TYPE_CC,2);										g=1;										break;									}									else if(*t ==3)									{										//This is CCID 3!                              #if DCP_DEBUG > 0										printk("%d: Got an ask for CCID 3\n",tp->whoami);#endif                              										tp->ccid=3;										genanswer(tp,DCP_NEG_TYPE_CC,3);										g=1; //I think this means we setup a CCID.#if DCP_DEBUG > 0										printk("INIT RECV TFRC\n");#endif										tp->recv_ccb = tfrc_recv_init(tp);										break;									}								}								// If none of the CCIDs in the ASK option are acceptable, tell the sender we like CCID 2								// SUGGESTION: We could also prefer CCID 3 as well!								if (!g)									genchoose (tp,DCP_NEG_TYPE_CC,2);							}							tp->negibuf |= 0x01;							break;						case DCP_NEG_TYPE_ACKRATIO: /* Ack Ratio negotiation */							if (!(tp->negibuf &0x02))							{								// Are we only allowing one byte for ack ratio option, specs suggest two bytes should be used - SHANE								if (p[3])								{									tp->ackratio = p[3];#if DCP_DEBUG > 1									printk ("%d: responding to ask ackratio by setting acratio to %d, and generating answer\n",tp->whoami,p[3]);#endif								}								genanswer (tp,DCP_NEG_TYPE_ACKRATIO,tp->ackratio);							}							tp->negibuf |= 0x02;							break;						case DCP_NEG_TYPE_ACKVECTOR: /* Send Ack Vector option negotiation */							if (!(tp->negibuf & 0x04))							{								if (p[3])								{									tp->uav = p[3];#if DCP_DEBUG > 1									printk ("%d: responding to ask use ackvector by setting uav to %d, and generating answer\n",tp->whoami,p[3]);#endif								}								genanswer (tp,DCP_NEG_TYPE_ACKVECTOR,p[3]);							}							tp->negibuf |= 0x04;							break;						/* I guess it's too bad if we get any other options come through - SHANE */						default:							break;					}				break;			/* A Prefer option where the feature location specifies the options it prefers */			case DCP_OPT_CHOOSE:				if ((eop-p)>=4)					switch (p[2])					{						// I guess we don't actually do anything in relation to the sender's preferred values.						// Instead, we just go into a negotiation state. If we don't do anything about this later						// on, I guess something could be done to make this better - SHANE						case DCP_NEG_TYPE_CC:							tp->ccid_state = DCP_OPT_STATE_ASKING;							break;						case DCP_NEG_TYPE_ACKRATIO:							tp->rcvr_ratio_state = DCP_OPT_STATE_ASKING;							break;						case DCP_NEG_TYPE_ACKVECTOR:							tp->uav_state = DCP_OPT_STATE_ASKING;							break;						default:							break;					}				break;			/* Confirm feature option */			// If Host A receives a confirm, that sets the value for the A to B half-connection			case DCP_OPT_ANSWER:				if ((eop-p)>=4)					switch (p[2])					{						case DCP_NEG_TYPE_CC:#if DCP_DEBUG > 1							printk ("%d confirmed assigned remote ccid of %d EEEEP %d\n",tp->whoami,p[3],tp->ccid);#endif							tp->ccid_state = DCP_OPT_STATE_KNOWN;							tp->ccid = p[3]; //Why is this not here before??                     #if DCP_DEBUG > 0							printk ("ccid of %d %d EEEEP\n",tp->whoami,p[3]);#endif                     							if (tp->ccid == 3)							{								///WOOOH lets call some fbd stuff								printk("LOADING TFRC\n");								tp->send_ccb = tfrc_send_init(tp); //This works too well it scares me lots							}							break;						case DCP_NEG_TYPE_ACKRATIO:#if DCP_DEBUG > 1							printk ("%d confirmed assigned remote ackratio of %d\n",tp->whoami,p[3]);#endif							tp->rcvr_ratio = p[3];							tp->rcvr_ratio_state = DCP_OPT_STATE_KNOWN;							break;						case DCP_NEG_TYPE_ACKVECTOR:#if DCP_DEBUG > 1							printk ("%d confirmed assigned remote use of ackvector of %d\n",tp->whoami,p[3]);#endif							tp->uav_state = DCP_OPT_STATE_KNOWN;							tp->uav = p[3];							break;						default:							break;					}				break;			// unknown feature number			default:				if (tp->opt_a_sz + 4 <=DCP_OPTASZ)				{					tp->opt_append[tp->opt_a_sz++] = DCP_OPT_IGNORED;					tp->opt_append[tp->opt_a_sz++] = 4;					tp->opt_append[tp->opt_a_sz++] = *p;					tp->opt_append[tp->opt_a_sz++] = ( (eop -p) > 2) ? p[2] : 0;				}				break;		}		p = eop;	}	return;}/* Puts a connection into the timewait state after receiving a RESET packet * * Parameters:	sk - the socket on which the connection is taking place * */static void enter_timewait (struct sock *sk){	struct dcp_opt *tp = &(sk->tp_pinfo.tp_dcp);#if DCP_DEBUG > 2	printk ("entering TIMEWAIT\n"); #endif	sk->state = DCP_TIMEWAIT;	tp->rto_num = 0x1000000;		// setting up a timer to expire when the timewait state should end	del_timer_sync (&tp->timewait_t);	tp->timewait_t.data = (unsigned long) sk;	tp->timewait_t.function = (void *) dcp_handle_timewait;	tp->timewait_t.expires = jiffies + DCP_TIMEWAIT_LEN;	add_timer (&tp->timewait_t);	return;}/* A continuation of processing a received packet. Here we deal with the acks attached to the packet, arrange * to ack this packet eventually, add the packet to the received queue, update the connection state if necessary, * and schedule the appropriate responses to CLOSEREQ, CLOSE and RESET packets * * Parameters:	sk - the socket on which the packet was received * 		skb - the sk_buff containing the received packet */static int dccp_enq_rcv (struct sock *sk, struct sk_buff *skb){	int err;	struct dcp_opt *tp = &(sk->tp_pinfo.tp_dcp);	unsigned char type;	err = 0;	type =skb->data[4];#if DCP_DEBUG > 2	printk ("PACKET IN: Whoami=%02X, Type=%02X, state=%d, length=%d, interrupt=%d\n",			tp->whoami,type,sk->state,skb->len,in_interrupt()); #endif	spin_lock (&tp->rsem);		dccp_update_ackn (&tp->ackn,skb); /* ackn is the ackn we send, taken from seqno in every pkt */	tp->unacked++;		/* protected by rsem */	increment_ackvector (sk, whatis_seqno (skb));	/* note that recvd packet has to be acked */	intake_acks (sk,skb,type);	/* give credit for acks received */	if (tp->whoami != WHOAMI_BINDER)		generic_option_parse (skb,sk);	if (tp->ccid ==3 && sk->state == DCP_OPEN) //don't do it if we're terming or everything will goto hell, and back	{//McManus does some dirty so we have to shift right 4 to play nice		tp->len_rcv = skb->len; //TODO is this right??		tp->type_rcv = skb->data[4] >> 4; 		tp->seq_rcv = whatis_seqno (skb); //Hope this works		tp->ack_rcv = dccp_whatis_ackn (skb);			tp->ndp_rcv = skb->data[9] & 0xf0;		tp->ndp_rcv >>=4;// shift it left buddy#if DCP_DEBUG > 2		printk("Tell TFRC about packet of type %d recieved with %d len of opts\n",				tp->type_rcv, (skb->data + (skb->data[8] * 4))				- ( skb->data + optionoffset (skb->data[4])));#endif		//tell tfrc about this packet, i bet it would like to know..		tfrc_send_packet_recv(tp->send_ccb,				skb->data + optionoffset (skb->data[4]),				(skb->data + (skb->data[8] * 4))				- ( skb->data + optionoffset (skb->data[4]))); 		tfrc_recv_packet_recv(tp->recv_ccb,				skb->data + optionoffset (skb->data[4]),				(skb->data + (skb->data[8] * 4))				- ( skb->data + optionoffset (skb->data[4]))); 	}	if ((type == TYPE_ACK) &&(sk->state == DCP_OPEN))	{		kfree_skb(skb);		/* todo - process options */		skb = NULL;	}	else		// check we have space in the receive queue for the packet		if (((tp->rcvq_t +1) %DCP_RCVQ_SZ) == tp->rcvq_h)			err = -ENOBUFS;		else		{			/* queue it */			tp->rcvq[tp->rcvq_t] = skb;			if (++tp->rcvq_t == DCP_RCVQ_SZ)				tp->rcvq_t = 0;		}	if (!err)	{        		//TODO [TOM] maybe need to add CCID 3 here!		/* if we've got too many unacked packets, we should schedule an		   ack - by the time that runs it may be obviated though. */		if ((tp->unacked >= tp->ackratio) &&				(!(tp->flags & FLAG_ACKSCHED)) &&				(tp->ccid == 2) &&				(sk->state == DCP_OPEN))		{			tp->atask.data =sk;			tp->flags |= FLAG_ACKSCHED;			schedule_task(&tp->atask);		}		// we've been asked to close the connection by the client		if ((tp->whoami == WHOAMI_SERVER) && 				((type == TYPE_CLOSE)||(type==TYPE_RESET))&& 				((sk->state == DCP_HALF_CLOSE) ||(sk->state == DCP_OPEN)) )		{			if ( (sk->state == DCP_OPEN) || (type == TYPE_CLOSE))			{				tp->rtask.data = sk;	/* send reset */				schedule_task(&tp->rtask);			}			sk->state = DCP_CLOSED; 		}		// we've been told by the server that the connection is being reset		if ((tp->whoami == WHOAMI_CLIENT) && 				(type==TYPE_RESET) && 				((sk->state == DCP_REQUESTING) || (sk->state == DCP_OPEN)) )		{#if DCP_DEBUG > 1			printk ("dccp client has been reset!\n");#endif			enter_timewait (sk);		}		// the server has sent us a close request		if ((tp->whoami == WHOAMI_CLIENT) && 				(type==TYPE_CLOSEREQ)&& 				(sk->state == DCP_OPEN))		{#if DCP_DEBUG > 2			printk ("closereq being acted upon\n");#endif			sk->state = DCP_HALF_CLOSE;			tp->ctask.data = sk;	/* send close */			schedule_task(&tp->ctask);		}	}	spin_unlock (&tp->rsem);	  	if (!err)		wake_up (&tp->newdata);	return err;}/* Performs initial processing on a received packet *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -