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

📄 raw.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 2 页
字号:
						 "raw sendmsg. Fix it!\n",						 current->comm);			err = -EINVAL;			if (usin->sin_family)				goto out;		}		daddr = usin->sin_addr.s_addr;		/* ANK: I did not forget to get protocol from port field.		 * I just do not know, who uses this weirdness.		 * IP_HDRINCL is much more convenient.		 */	} else {		err = -EINVAL;		if (sk->state != TCP_ESTABLISHED) 			goto out;		daddr = sk->daddr;	}	ipc.addr = sk->saddr;	ipc.opt = NULL;	ipc.oif = sk->bound_dev_if;	if (msg->msg_controllen) {		err = ip_cmsg_send(msg, &ipc);		if (err)			goto out;		if (ipc.opt)			free = 1;	}	rfh.saddr = ipc.addr;	ipc.addr = daddr;	if (!ipc.opt)		ipc.opt = sk->protinfo.af_inet.opt;	if (ipc.opt) {		err = -EINVAL;		/* Linux does not mangle headers on raw sockets,		 * so that IP options + IP_HDRINCL is non-sense.		 */		if (sk->protinfo.af_inet.hdrincl)			goto done;		if (ipc.opt->srr) {			if (!daddr)				goto done;			daddr = ipc.opt->faddr;		}	}	tos = RT_TOS(sk->protinfo.af_inet.tos) | sk->localroute;	if (msg->msg_flags & MSG_DONTROUTE)		tos |= RTO_ONLINK;	if (MULTICAST(daddr)) {		if (!ipc.oif)			ipc.oif = sk->protinfo.af_inet.mc_index;		if (!rfh.saddr)			rfh.saddr = sk->protinfo.af_inet.mc_addr;	}	err = ip_route_output(&rt, daddr, rfh.saddr, tos, ipc.oif);	if (err)		goto done;	err = -EACCES;	if (rt->rt_flags & RTCF_BROADCAST && !sk->broadcast)		goto done;	if (msg->msg_flags & MSG_CONFIRM)		goto do_confirm;back_from_confirm:	rfh.iov		= msg->msg_iov;	rfh.saddr	= rt->rt_src;	rfh.dst		= &rt->u.dst;	if (!ipc.addr)		ipc.addr = rt->rt_dst;	err = ip_build_xmit(sk, sk->protinfo.af_inet.hdrincl ? raw_getrawfrag :		       	    raw_getfrag, &rfh, len, &ipc, rt, msg->msg_flags);done:	if (free)		kfree(ipc.opt);	ip_rt_put(rt);out:	return err < 0 ? err : len;do_confirm:	dst_confirm(&rt->u.dst);	if (!(msg->msg_flags & MSG_PROBE) || len)		goto back_from_confirm;	err = 0;	goto done;}static void raw_close(struct sock *sk, long timeout){        /*	 * Raw sockets may have direct kernel refereneces. Kill them.	 */	ip_ra_control(sk, 0, NULL);	inet_sock_release(sk);}/* This gets rid of all the nasties in af_inet. -DaveM */static int raw_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len){	struct sockaddr_in *addr = (struct sockaddr_in *) uaddr;	int ret = -EINVAL;	int chk_addr_ret;	if (sk->state != TCP_CLOSE || addr_len < sizeof(struct sockaddr_in))		goto out;	chk_addr_ret = inet_addr_type(addr->sin_addr.s_addr);	ret = -EADDRNOTAVAIL;	if (addr->sin_addr.s_addr && chk_addr_ret != RTN_LOCAL &&	    chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST)		goto out;	sk->rcv_saddr = sk->saddr = addr->sin_addr.s_addr;	if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)		sk->saddr = 0;  /* Use device */	sk_dst_reset(sk);	ret = 0;out:	return ret;}/* *	This should be easy, if there is something there *	we return it, otherwise we block. */int raw_recvmsg(struct sock *sk, struct msghdr *msg, int len,		int noblock, int flags, int *addr_len){	int copied = 0;	int err = -EOPNOTSUPP;	struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name;	struct sk_buff *skb;	if (flags & MSG_OOB)		goto out;	if (addr_len)		*addr_len = sizeof(*sin);	if (flags & MSG_ERRQUEUE) {		err = ip_recv_error(sk, msg, len);		goto out;	}	skb = skb_recv_datagram(sk, flags, noblock, &err);	if (!skb)		goto out;	copied = skb->len;	if (len < copied) {		msg->msg_flags |= MSG_TRUNC;		copied = len;	}	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);	if (err)		goto done;	sock_recv_timestamp(msg, sk, skb);	/* Copy the address. */	if (sin) {		sin->sin_family = AF_INET;		sin->sin_addr.s_addr = skb->nh.iph->saddr;		memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));	}	if (sk->protinfo.af_inet.cmsg_flags)		ip_cmsg_recv(msg, skb);done:	skb_free_datagram(sk, skb);out:	return err ? : copied;}static int raw_init(struct sock *sk){	struct raw_opt *tp = &(sk->tp_pinfo.tp_raw4);	if (sk->num == IPPROTO_ICMP)		memset(&tp->filter, 0, sizeof(tp->filter));	return 0;}static int raw_seticmpfilter(struct sock *sk, char *optval, int optlen){	if (optlen > sizeof(struct icmp_filter))		optlen = sizeof(struct icmp_filter);	if (copy_from_user(&sk->tp_pinfo.tp_raw4.filter, optval, optlen))		return -EFAULT;	return 0;}static int raw_geticmpfilter(struct sock *sk, char *optval, int *optlen){	int len, ret = -EFAULT;	if (get_user(len, optlen))		goto out;	ret = -EINVAL;	if (len < 0)		goto out;	if (len > sizeof(struct icmp_filter))		len = sizeof(struct icmp_filter);	ret = -EFAULT;	if (put_user(len, optlen) ||	    copy_to_user(optval, &sk->tp_pinfo.tp_raw4.filter, len))		goto out;	ret = 0;out:	return ret;}static int raw_setsockopt(struct sock *sk, int level, int optname, 			  char *optval, int optlen){	if (level != SOL_RAW)		return ip_setsockopt(sk, level, optname, optval, optlen);	if (optname == ICMP_FILTER) {		if (sk->num != IPPROTO_ICMP)			return -EOPNOTSUPP;		else			return raw_seticmpfilter(sk, optval, optlen);	}	return -ENOPROTOOPT;}static int raw_getsockopt(struct sock *sk, int level, int optname, 			  char *optval, int *optlen){	if (level != SOL_RAW)		return ip_getsockopt(sk, level, optname, optval, optlen);	if (optname == ICMP_FILTER) {		if (sk->num != IPPROTO_ICMP)			return -EOPNOTSUPP;		else			return raw_geticmpfilter(sk, optval, optlen);	}	return -ENOPROTOOPT;}static int raw_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->len;			spin_unlock_irq(&sk->receive_queue.lock);			return put_user(amount, (int *)arg);		}		default:#ifdef CONFIG_IP_MROUTE			return ipmr_ioctl(sk, cmd, arg);#else			return -ENOIOCTLCMD;#endif	}}static void get_raw_sock(struct sock *sp, char *tmpbuf, int i){	unsigned int dest = sp->daddr,		     src = sp->rcv_saddr;	__u16 destp = 0,	      srcp  = sp->num;	sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %ld %d %p",		i, src, srcp, dest, 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 raw_get_info(char *buffer, char **start, off_t offset, int length){	int len = 0, num = 0, i;	off_t pos = 128;	off_t begin;	char tmpbuf[129];	if (offset < 128) 		len += sprintf(buffer, "%-127s\n",			       "  sl  local_address rem_address   st tx_queue "			       "rx_queue tr tm->when retrnsmt   uid  timeout "			       "inode");	read_lock(&raw_v4_lock);	for (i = 0; i < RAWV4_HTABLE_SIZE; i++) {		struct sock *sk;		for (sk = raw_v4_htable[i]; sk; sk = sk->next, num++) {			if (sk->family != PF_INET)				continue;			pos += 128;			if (pos <= offset)				continue;			get_raw_sock(sk, tmpbuf, i);			len += sprintf(buffer + len, "%-127s\n", tmpbuf);			if (len >= length)				goto out;		}	}out:	read_unlock(&raw_v4_lock);	begin = len - (pos - offset);	*start = buffer + begin;	len -= begin;	if (len > length)		len = length;	if (len < 0)		len = 0; 	return len;}struct proto raw_prot = {	name:		"RAW",	close:		raw_close,	connect:	udp_connect,	disconnect:	udp_disconnect,	ioctl:		raw_ioctl,	init:		raw_init,	setsockopt:	raw_setsockopt,	getsockopt:	raw_getsockopt,	sendmsg:	raw_sendmsg,	recvmsg:	raw_recvmsg,	bind:		raw_bind,	backlog_rcv:	raw_rcv_skb,	hash:		raw_v4_hash,	unhash:		raw_v4_unhash,};

⌨️ 快捷键说明

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