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

📄 udp_usrreq.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
	struct mbuf *addr, *control;{	register struct udpiphdr *ui;	register int len = m->m_pkthdr.len;	struct in_addr laddr;	int s = 0, error = 0;	if (control)		m_freem(control);		/* XXX */	if (len + sizeof(struct udpiphdr) > IP_MAXPACKET) {		error = EMSGSIZE;		goto release;	}	if (addr) {		laddr = inp->inp_laddr;		if (inp->inp_faddr.s_addr != INADDR_ANY) {			error = EISCONN;			goto release;		}		/*		 * Must block input while temporarily connected.		 */		s = splnet();		error = in_pcbconnect(inp, addr);		if (error) {			splx(s);			goto release;		}	} else {		if (inp->inp_faddr.s_addr == INADDR_ANY) {			error = ENOTCONN;			goto release;		}	}	/*	 * Calculate data length and get a mbuf	 * for UDP and IP headers.	 */	M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);	if (m == 0) {		error = ENOBUFS;		if (addr)			splx(s);		goto release;	}	/*	 * Fill in mbuf with extended UDP header	 * and addresses and length put into network format.	 */	ui = mtod(m, struct udpiphdr *);	ui->ui_next = ui->ui_prev = 0;	ui->ui_x1 = 0;	ui->ui_pr = IPPROTO_UDP;	ui->ui_len = htons((u_short)len + sizeof (struct udphdr));	ui->ui_src = inp->inp_laddr;	ui->ui_dst = inp->inp_faddr;	ui->ui_sport = inp->inp_lport;	ui->ui_dport = inp->inp_fport;	ui->ui_ulen = ui->ui_len;	/*	 * Stuff checksum and output datagram.	 */	ui->ui_sum = 0;	if (udpcksum) {	    if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0)		ui->ui_sum = 0xffff;	}	((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;	((struct ip *)ui)->ip_ttl = inp->inp_ip_ttl;	/* XXX */	((struct ip *)ui)->ip_tos = inp->inp_ip_tos;	/* XXX */	udpstat.udps_opackets++;	error = ip_output(m, inp->inp_options, &inp->inp_route,	    inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST),	    inp->inp_moptions);	if (addr) {		in_pcbdisconnect(inp);		inp->inp_laddr = laddr;		splx(s);	}	return (error);release:	m_freem(m);	return (error);}#ifdef __rtems__#define INP_INFO_RLOCK(a)#define INP_INFO_RUNLOCK(a)#define INP_LOCK(a)#define INP_UNLOCK(a)#endifstatic intudp_pcblist(SYSCTL_HANDLER_ARGS){	int error, i, n, s;	struct inpcb *inp, **inp_list;	inp_gen_t gencnt;	struct xinpgen xig;	/*	 * The process of preparing the TCB list is too time-consuming and	 * resource-intensive to repeat twice on every request.	 */	if (req->oldptr == 0) {		n = udbinfo.ipi_count;		req->oldidx = 2 * (sizeof xig)			+ (n + n/8) * sizeof(struct xinpcb);		return 0;	}	if (req->newptr != 0)		return EPERM;	/*	 * OK, now we're committed to doing something.	 */	s = splnet();	gencnt = udbinfo.ipi_gencnt;	n = udbinfo.ipi_count;	splx(s);	sysctl_wire_old_buffer(req, 2 * (sizeof xig)		+ n * sizeof(struct xinpcb));	xig.xig_len = sizeof xig;	xig.xig_count = n;	xig.xig_gen = gencnt;#if 0	xig.xig_sogen = so_gencnt;#endif	error = SYSCTL_OUT(req, &xig, sizeof xig);	if (error)		return error;  /* ccj add the exit if count is 0 */  if (!n)    return error;  	inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);	if (inp_list == 0)		return ENOMEM;		s = splnet();	INP_INFO_RLOCK(&udbinfo);	for (inp = LIST_FIRST(udbinfo.listhead), i = 0; inp && i < n;	     inp = LIST_NEXT(inp, inp_list)) {		INP_LOCK(inp);		if (inp->inp_gencnt <= gencnt)#if 0      &&		    cr_canseesocket(req->td->td_ucred, inp->inp_socket) == 0)#endif			inp_list[i++] = inp;		INP_UNLOCK(inp);	}	INP_INFO_RUNLOCK(&udbinfo);	splx(s);	n = i;	error = 0;	for (i = 0; i < n; i++) {		inp = inp_list[i];		INP_LOCK(inp);		if (inp->inp_gencnt <= gencnt) {			struct xinpcb xi;			xi.xi_len = sizeof xi;			/* XXX should avoid extra copy */			bcopy(inp, &xi.xi_inp, sizeof *inp);#if 0			if (inp->inp_socket)				sotoxsocket(inp->inp_socket, &xi.xi_socket);#endif			error = SYSCTL_OUT(req, &xi, sizeof xi);		}		INP_UNLOCK(inp);	}	if (!error) {		/*		 * Give the user an updated idea of our state.		 * If the generation differs from what we told		 * her before, she knows that something happened		 * while we were processing this request, and it		 * might be necessary to retry.		 */		s = splnet();		INP_INFO_RLOCK(&udbinfo);		xig.xig_gen = udbinfo.ipi_gencnt;#if 0		xig.xig_sogen = so_gencnt;#endif		xig.xig_count = udbinfo.ipi_count;		INP_INFO_RUNLOCK(&udbinfo);		splx(s);		error = SYSCTL_OUT(req, &xig, sizeof xig);	}	free(inp_list, M_TEMP);	return error;}SYSCTL_PROC(_net_inet_udp, UDPCTL_PCBLIST, pcblist, CTLFLAG_RD, 0, 0,	    udp_pcblist, "S,xinpcb", "List of active UDP sockets");static u_long	udp_sendspace = 9216;		/* really max datagram size */					/* 40 1K datagrams */SYSCTL_INT(_net_inet_udp, UDPCTL_MAXDGRAM, maxdgram, CTLFLAG_RW,	&udp_sendspace, 0, "");static u_long	udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in));SYSCTL_INT(_net_inet_udp, UDPCTL_RECVSPACE, recvspace, CTLFLAG_RW,	&udp_recvspace, 0, "");/*ARGSUSED*/intudp_usrreq(so, req, m, addr, control)	struct socket *so;	int req;	struct mbuf *m, *addr, *control;{	struct inpcb *inp = sotoinpcb(so);	int error = 0;	int s;	if (req == PRU_CONTROL)		return (in_control(so, (u_long)m, (caddr_t)addr,			(struct ifnet *)control));	if (inp == NULL && req != PRU_ATTACH) {		error = EINVAL;		goto release;	}	/*	 * Note: need to block udp_input while changing	 * the udp pcb queue and/or pcb addresses.	 */	switch (req) {	case PRU_ATTACH:		if (inp != NULL) {			error = EINVAL;			break;		}		s = splnet();		error = in_pcballoc(so, &udbinfo);		splx(s);		if (error)			break;		error = soreserve(so, udp_sendspace, udp_recvspace);		if (error)			break;		((struct inpcb *) so->so_pcb)->inp_ip_ttl = ip_defttl;		break;	case PRU_DETACH:		udp_detach(inp);		break;	case PRU_BIND:		s = splnet();		error = in_pcbbind(inp, addr);		splx(s);		break;	case PRU_LISTEN:		error = EOPNOTSUPP;		break;	case PRU_CONNECT:		if (inp->inp_faddr.s_addr != INADDR_ANY) {			error = EISCONN;			break;		}		s = splnet();		error = in_pcbconnect(inp, addr);		splx(s);		if (error == 0)			soisconnected(so);		break;	case PRU_CONNECT2:		error = EOPNOTSUPP;		break;	case PRU_ACCEPT:		error = EOPNOTSUPP;		break;	case PRU_DISCONNECT:		if (inp->inp_faddr.s_addr == INADDR_ANY) {			error = ENOTCONN;			break;		}		s = splnet();		in_pcbdisconnect(inp);		inp->inp_laddr.s_addr = INADDR_ANY;		splx(s);		so->so_state &= ~SS_ISCONNECTED;		/* XXX */		break;	case PRU_SHUTDOWN:		socantsendmore(so);		break;	case PRU_SEND:		return (udp_output(inp, m, addr, control));	case PRU_ABORT:		soisdisconnected(so);		udp_detach(inp);		break;	case PRU_SOCKADDR:		in_setsockaddr(inp, addr);		break;	case PRU_PEERADDR:		in_setpeeraddr(inp, addr);		break;	case PRU_SENSE:		/*		 * stat: don't bother with a blocksize.		 */		return (0);	case PRU_SENDOOB:	case PRU_FASTTIMO:	case PRU_SLOWTIMO:	case PRU_PROTORCV:	case PRU_PROTOSEND:		error =  EOPNOTSUPP;		break;	case PRU_RCVD:	case PRU_RCVOOB:		return (EOPNOTSUPP);	/* do not free mbuf's */	default:		panic("udp_usrreq");	}release:	if (control) {		printf("udp control data unexpectedly retained\n");		m_freem(control);	}	if (m)		m_freem(m);	return (error);}static voidudp_detach(inp)	struct inpcb *inp;{	int s = splnet();	in_pcbdetach(inp);	splx(s);}

⌨️ 快捷键说明

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