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

📄 raw.c

📁 嵌入式系统设计与实验教材二源码linux内核移植与编译
💻 C
📖 第 1 页 / 共 2 页
字号:
			csum = (__u16 *) (buff + opt->offset);			*csum = hdr->cksum;		} else {			if (net_ratelimit())				printk(KERN_DEBUG "icmp: cksum offset too big\n");			return -EINVAL;		}	}		return 0; }static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, int len){	struct ipv6_txoptions opt_space;	struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name;	struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;	struct ipv6_txoptions *opt = NULL;	struct ip6_flowlabel *flowlabel = NULL;	struct flowi fl;	int addr_len = msg->msg_namelen;	struct in6_addr *daddr;	struct raw6_opt *raw_opt;	int hlimit = -1;	u16 proto;	int err;	/* Rough check on arithmetic overflow,	   better check is made in ip6_build_xmit	 */	if (len < 0)		return -EMSGSIZE;	/* Mirror BSD error message compatibility */	if (msg->msg_flags & MSG_OOB)				return -EOPNOTSUPP;	/*	 *	Get and verify the address. 	 */	fl.fl6_flowlabel = 0;	fl.oif = 0;	if (sin6) {		if (addr_len < SIN6_LEN_RFC2133) 			return -EINVAL;		if (sin6->sin6_family && sin6->sin6_family != AF_INET6) 			return(-EINVAL);		/* port is the proto value [0..255] carried in nexthdr */		proto = ntohs(sin6->sin6_port);		if (!proto)			proto = sk->num;		if (proto > 255)			return(-EINVAL);		daddr = &sin6->sin6_addr;		if (np->sndflow) {			fl.fl6_flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK;			if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) {				flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);				if (flowlabel == NULL)					return -EINVAL;				daddr = &flowlabel->dst;			}		}		/* Otherwise it will be difficult to maintain sk->dst_cache. */		if (sk->state == TCP_ESTABLISHED &&		    !ipv6_addr_cmp(daddr, &sk->net_pinfo.af_inet6.daddr))			daddr = &sk->net_pinfo.af_inet6.daddr;		if (addr_len >= sizeof(struct sockaddr_in6) &&		    sin6->sin6_scope_id &&		    ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL)			fl.oif = sin6->sin6_scope_id;	} else {		if (sk->state != TCP_ESTABLISHED) 			return(-EINVAL);				proto = sk->num;		daddr = &(sk->net_pinfo.af_inet6.daddr);		fl.fl6_flowlabel = np->flow_label;	}	if (ipv6_addr_any(daddr)) {		/* 		 * unspecfied destination address 		 * treated as error... is this correct ?		 */		return(-EINVAL);	}	if (fl.oif == 0)		fl.oif = sk->bound_dev_if;	fl.fl6_src = NULL;	if (msg->msg_controllen) {		opt = &opt_space;		memset(opt, 0, sizeof(struct ipv6_txoptions));		err = datagram_send_ctl(msg, &fl, opt, &hlimit);		if (err < 0) {			fl6_sock_release(flowlabel);			return err;		}		if ((fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) {			flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);			if (flowlabel == NULL)				return -EINVAL;		}		if (!(opt->opt_nflen|opt->opt_flen))			opt = NULL;	}	if (opt == NULL)		opt = np->opt;	if (flowlabel)		opt = fl6_merge_options(&opt_space, flowlabel, opt);	raw_opt = &sk->tp_pinfo.tp_raw;	fl.proto = proto;	fl.fl6_dst = daddr;	if (fl.fl6_src == NULL && !ipv6_addr_any(&np->saddr))		fl.fl6_src = &np->saddr;	fl.uli_u.icmpt.type = 0;	fl.uli_u.icmpt.code = 0;		if (raw_opt->checksum) {		struct rawv6_fakehdr hdr;				hdr.iov = msg->msg_iov;		hdr.sk  = sk;		hdr.len = len;		hdr.cksum = 0;		hdr.proto = proto;		if (opt && opt->srcrt)			hdr.daddr = daddr;		else			hdr.daddr = NULL;		err = ip6_build_xmit(sk, rawv6_frag_cksum, &hdr, &fl, len,				     opt, hlimit, msg->msg_flags);	} else {		err = ip6_build_xmit(sk, rawv6_getfrag, msg->msg_iov, &fl, len,				     opt, hlimit, msg->msg_flags);	}	fl6_sock_release(flowlabel);	return err<0?err:len;}static int rawv6_seticmpfilter(struct sock *sk, int level, int optname, 			       char *optval, int optlen){	switch (optname) {	case ICMPV6_FILTER:		if (optlen > sizeof(struct icmp6_filter))			optlen = sizeof(struct icmp6_filter);		if (copy_from_user(&sk->tp_pinfo.tp_raw.filter, optval, optlen))			return -EFAULT;		return 0;	default:		return -ENOPROTOOPT;	};	return 0;}static int rawv6_geticmpfilter(struct sock *sk, int level, int optname, 			       char *optval, int *optlen){	int len;	switch (optname) {	case ICMPV6_FILTER:		if (get_user(len, optlen))			return -EFAULT;		if (len < 0)			return -EINVAL;		if (len > sizeof(struct icmp6_filter))			len = sizeof(struct icmp6_filter);		if (put_user(len, optlen))			return -EFAULT;		if (copy_to_user(optval, &sk->tp_pinfo.tp_raw.filter, len))			return -EFAULT;		return 0;	default:		return -ENOPROTOOPT;	};	return 0;}static int rawv6_setsockopt(struct sock *sk, int level, int optname, 			    char *optval, int optlen){	struct raw6_opt *opt = &sk->tp_pinfo.tp_raw;	int val;	switch(level) {		case SOL_RAW:			break;		case SOL_ICMPV6:			if (sk->num != IPPROTO_ICMPV6)				return -EOPNOTSUPP;			return rawv6_seticmpfilter(sk, level, optname, optval,						   optlen);		case SOL_IPV6:			if (optname == IPV6_CHECKSUM)				break;		default:			return ipv6_setsockopt(sk, level, optname, optval,					       optlen);	};  	if (get_user(val, (int *)optval))		return -EFAULT;	switch (optname) {		case IPV6_CHECKSUM:			if (val < 0) {				opt->checksum = 0;			} else {				opt->checksum = 1;				opt->offset = val;			}			return 0;			break;		default:			return(-ENOPROTOOPT);	}}static int rawv6_getsockopt(struct sock *sk, int level, int optname, 			    char *optval, int *optlen){	struct raw6_opt *opt = &sk->tp_pinfo.tp_raw;	int val, len;	switch(level) {		case SOL_RAW:			break;		case SOL_ICMPV6:			if (sk->num != IPPROTO_ICMPV6)				return -EOPNOTSUPP;			return rawv6_geticmpfilter(sk, level, optname, optval,						   optlen);		case SOL_IPV6:			if (optname == IPV6_CHECKSUM)				break;		default:			return ipv6_getsockopt(sk, level, optname, optval,					       optlen);	};	if (get_user(len,optlen))		return -EFAULT;	switch (optname) {	case IPV6_CHECKSUM:		if (opt->checksum == 0)			val = -1;		else			val = opt->offset;	default:		return -ENOPROTOOPT;	}	len = min_t(unsigned int, sizeof(int), len);	if (put_user(len, optlen))		return -EFAULT;	if (copy_to_user(optval,&val,len))		return -EFAULT;	return 0;}static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg){	switch(cmd) {		case SIOCOUTQ:		{			int amount = atomic_read(&sk->wmem_alloc);			return put_user(amount, (int *)arg);		}		case SIOCINQ:		{			struct sk_buff *skb;			int amount = 0;			spin_lock_irq(&sk->receive_queue.lock);			skb = skb_peek(&sk->receive_queue);			if (skb != NULL)				amount = skb->tail - skb->h.raw;			spin_unlock_irq(&sk->receive_queue.lock);			return put_user(amount, (int *)arg);		}		default:			return -ENOIOCTLCMD;	}}static void rawv6_close(struct sock *sk, long timeout){	if (sk->num == IPPROTO_RAW)		ip6_ra_control(sk, -1, NULL);	inet_sock_release(sk);}static int rawv6_init_sk(struct sock *sk){	return(0);}#define LINE_LEN 190#define LINE_FMT "%-190s\n"static void get_raw6_sock(struct sock *sp, char *tmpbuf, int i){	struct in6_addr *dest, *src;	__u16 destp, srcp;	dest  = &sp->net_pinfo.af_inet6.daddr;	src   = &sp->net_pinfo.af_inet6.rcv_saddr;	destp = 0;	srcp  = sp->num;	sprintf(tmpbuf,		"%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "		"%02X %08X:%08X %02X:%08lX %08X %5d %8d %ld %d %p",		i,		src->s6_addr32[0], src->s6_addr32[1],		src->s6_addr32[2], src->s6_addr32[3], srcp,		dest->s6_addr32[0], dest->s6_addr32[1],		dest->s6_addr32[2], dest->s6_addr32[3], destp,		sp->state, 		atomic_read(&sp->wmem_alloc), atomic_read(&sp->rmem_alloc),		0, 0L, 0,		sock_i_uid(sp), 0,		sock_i_ino(sp),		atomic_read(&sp->refcnt), sp);}int raw6_get_info(char *buffer, char **start, off_t offset, int length){	int len = 0, num = 0, i;	off_t pos = 0;	off_t begin;	char tmpbuf[LINE_LEN+2];	if (offset < LINE_LEN+1)		len += sprintf(buffer, LINE_FMT,			       "  sl  "						/* 6 */			       "local_address                         "		/* 38 */			       "remote_address                        "		/* 38 */			       "st tx_queue rx_queue tr tm->when retrnsmt"	/* 41 */			       "   uid  timeout inode");			/* 21 */										/*----*/										/*144 */	pos = LINE_LEN+1;	read_lock(&raw_v6_lock);	for (i = 0; i < RAWV6_HTABLE_SIZE; i++) {		struct sock *sk;		for (sk = raw_v6_htable[i]; sk; sk = sk->next, num++) {			if (sk->family != PF_INET6)				continue;			pos += LINE_LEN+1;			if (pos <= offset)				continue;			get_raw6_sock(sk, tmpbuf, i);			len += sprintf(buffer+len, LINE_FMT, tmpbuf);			if(len >= length)				goto out;		}	}out:	read_unlock(&raw_v6_lock);	begin = len - (pos - offset);	*start = buffer + begin;	len -= begin;	if(len > length)		len = length;	if (len < 0)		len = 0; 	return len;}struct proto rawv6_prot = {	name:		"RAW",	close:		rawv6_close,	connect:	udpv6_connect,	disconnect:	udp_disconnect,	ioctl:		rawv6_ioctl,	init:		rawv6_init_sk,	destroy:	inet6_destroy_sock,	setsockopt:	rawv6_setsockopt,	getsockopt:	rawv6_getsockopt,	sendmsg:	rawv6_sendmsg,	recvmsg:	rawv6_recvmsg,	bind:		rawv6_bind,	backlog_rcv:	rawv6_rcv_skb,	hash:		raw_v6_hash,	unhash:		raw_v6_unhash,};

⌨️ 快捷键说明

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