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

📄 udp.c

📁 一个Windows下的Linux专用虚拟机
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1982, 1986, 1988, 1990, 1993 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *	@(#)udp_usrreq.c	8.4 (Berkeley) 1/21/94 * udp_usrreq.c,v 1.4 1994/10/02 17:48:45 phk Exp *//* * Changes and additions relating to SLiRP * Copyright (c) 1995 Danny Gasparovski. *  * Please read the file COPYRIGHT for the  * terms and conditions of the copyright. */#include "slirp.h"#include "ip_icmp.h"struct udpstat udpstat;struct socket udb;/* * UDP protocol implementation. * Per RFC 768, August, 1980. */#ifndef	COMPAT_42int	udpcksum = 1;#elseint	udpcksum = 0;		/* XXX */#endifstruct	socket *udp_last_so = &udb;/* incrase receive buffer (win32 default: 8k) */static const int max_rcvbuf_size = 32768;voidudp_init(){	udb.so_next = udb.so_prev = &udb;}/* m->m_data  points at ip packet header  * m->m_len   length ip packet  * ip->ip_len length data (IPDU) */voidudp_input(m, iphlen)	register struct mbuf *m;	int iphlen;{	register struct ip *ip;	register struct udphdr *uh;/*	struct mbuf *opts = 0;*/	int len;	struct ip save_ip; 	struct socket *so;		DEBUG_CALL("udp_input");	DEBUG_ARG("m = %lx", (long)m);	DEBUG_ARG("iphlen = %d", iphlen);		udpstat.udps_ipackets++;	/*	 * Strip IP options, if any; should skip this,	 * make available to user, and use on returned packets,	 * but we don't yet have a way to check the checksum	 * with options still present.	 */	if(iphlen > sizeof(struct ip)) {		ip_stripoptions(m, (struct mbuf *)0);		iphlen = sizeof(struct ip);	}	/*	 * Get IP and UDP header together in first mbuf.	 */	ip = mtod(m, struct ip *);	uh = (struct udphdr *)((caddr_t)ip + iphlen);	/*	 * Make mbuf data length reflect UDP length.	 * If not enough data to reflect UDP length, drop.	 */	len = ntohs((u_int16_t)uh->uh_ulen);	if (ip->ip_len != len) {		if (len > ip->ip_len) {			udpstat.udps_badlen++;			goto bad;		}		m_adj(m, len - ip->ip_len);		ip->ip_len = len;	}		/*	 * Save a copy of the IP header in case we want restore it	 * for sending an ICMP error message in response.	 */	save_ip = *ip; 	save_ip.ip_len+= iphlen;         /* tcp_input subtracts this */	/*	 * Checksum extended UDP header and data.	 */	if (udpcksum && uh->uh_sum) {	  ((struct ipovly *)ip)->ih_next = 0;	  ((struct ipovly *)ip)->ih_prev = 0;	  ((struct ipovly *)ip)->ih_x1 = 0;	  ((struct ipovly *)ip)->ih_len = uh->uh_ulen;	  /* keep uh_sum for ICMP reply	   * uh->uh_sum = cksum(m, len + sizeof (struct ip)); 	   * if (uh->uh_sum) { 	   */	  if(cksum(m, len + sizeof(struct ip))) {	    udpstat.udps_badsum++;	    goto bad;	  }	}        /*         *  handle DHCP/BOOTP         */        if (ntohs(uh->uh_dport) == BOOTP_SERVER) {            bootp_input(m);            goto bad;        }#ifdef EMULATE_TFTP_SERVER        /*         *  handle TFTP         */        if (ntohs(uh->uh_dport) == TFTP_SERVER) {            tftp_input(m);            goto bad;        }#endif	/*	 * Locate pcb for datagram.	 */	so = udp_last_so;	if (so->so_lport != uh->uh_sport ||	    so->so_laddr.s_addr != ip->ip_src.s_addr) {		struct socket *tmp;				for (tmp = udb.so_next; tmp != &udb; tmp = tmp->so_next) {			if (tmp->so_lport == uh->uh_sport &&			    tmp->so_laddr.s_addr == ip->ip_src.s_addr) {				so = tmp;				break;			}		}		if (tmp == &udb) {		  so = NULL;		} else {		  udpstat.udpps_pcbcachemiss++;		  udp_last_so = so;		}	}		if (so != NULL) {	  so->so_faddr = ip->ip_dst;	  so->so_fport = uh->uh_dport;	} else {	  /*	   * If there's no socket for this packet,	   * create one	   */	  if ((so = socreate()) == NULL) goto bad;	  if(udp_attach(so) == -1) {	    DEBUG_MISC((dfd," udp_attach errno = %d-%s\n", 			errno,strerror(errno)));	    sofree(so);	    goto bad;	  }	  	  /*	   * Setup fields	   */	  /* udp_last_so = so; */	  so->so_laddr = ip->ip_src;	  so->so_lport = uh->uh_sport;	  so->so_faddr = ip->ip_dst; /* XXX */	  so->so_fport = uh->uh_dport; /* XXX */	  	  if ((so->so_iptos = udp_tos(so)) == 0)	    so->so_iptos = ip->ip_tos;	  	  /*	   * XXXXX Here, check if it's in udpexec_list,	   * and if it is, do the fork_exec() etc.	   */	}	iphlen += sizeof(struct udphdr);	m->m_len -= iphlen;	m->m_data += iphlen;	/*	 * Now we sendto() the packet.	 */	if (so->so_emu)	   udp_emu(so, m);	if(sosendto(so,m) == -1) {	  m->m_len += iphlen;	  m->m_data -= iphlen;	  *ip=save_ip;	  DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno)));	  icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));  	}	m_free(so->so_m);   /* used for ICMP if error on sorecvfrom */	/* restore the orig mbuf packet */	m->m_len += iphlen;	m->m_data -= iphlen;	*ip=save_ip;	so->so_m=m;         /* ICMP backup */	return;bad:	m_freem(m);	/* if (opts) m_freem(opts); */	return;}int udp_output2(struct socket *so, struct mbuf *m,                 struct sockaddr_in *saddr, struct sockaddr_in *daddr,                int iptos){	register struct udpiphdr *ui;	int error = 0;	DEBUG_CALL("udp_output");	DEBUG_ARG("so = %lx", (long)so);	DEBUG_ARG("m = %lx", (long)m);	DEBUG_ARG("saddr = %lx", (long)saddr->sin_addr.s_addr);	DEBUG_ARG("daddr = %lx", (long)daddr->sin_addr.s_addr);	/*	 * Adjust for header	 */	m->m_data -= sizeof(struct udpiphdr);	m->m_len += sizeof(struct udpiphdr);		/*	 * 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(m->m_len - sizeof(struct ip)); /* + sizeof (struct udphdr)); */	/* XXXXX Check for from-one-location sockets, or from-any-location sockets */        ui->ui_src = saddr->sin_addr;	ui->ui_dst = daddr->sin_addr;	ui->ui_sport = saddr->sin_port;	ui->ui_dport = daddr->sin_port;	ui->ui_ulen = ui->ui_len;	/*	 * Stuff checksum and output datagram.	 */	ui->ui_sum = 0;	if (udpcksum) {	    if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0)		ui->ui_sum = 0xffff;	}	((struct ip *)ui)->ip_len = m->m_len;	((struct ip *)ui)->ip_ttl = ip_defttl;	((struct ip *)ui)->ip_tos = iptos;		udpstat.udps_opackets++;		error = ip_output(so, m);		return (error);}int udp_output(struct socket *so, struct mbuf *m,                struct sockaddr_in *addr){    struct sockaddr_in saddr, daddr;    saddr = *addr;    if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {        saddr.sin_addr.s_addr = so->so_faddr.s_addr;        if ((so->so_faddr.s_addr & htonl(0x000000ff)) == htonl(0xff))            saddr.sin_addr.s_addr = alias_addr.s_addr;    }    daddr.sin_addr = so->so_laddr;    daddr.sin_port = so->so_lport;        return udp_output2(so, m, &saddr, &daddr, so->so_iptos);}intudp_attach(so)     struct socket *so;{  struct sockaddr_in addr;	  if((so->s = socket(AF_INET,SOCK_DGRAM,0)) != -1) {    /*     * Here, we bind() the socket.  Although not really needed     * (sendto() on an unbound socket will bind it), it's done     * here so that emulation of ytalk etc. don't have to do it     */    addr.sin_family = AF_INET;    addr.sin_port = 0;    addr.sin_addr.s_addr = INADDR_ANY;    if(bind(so->s, (struct sockaddr *)&addr, sizeof(addr))<0) {

⌨️ 快捷键说明

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