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

📄 arp.c

📁 这是一个SIGMA方案的PMP播放器的UCLINUX程序,可播放DVD,VCD,CD MP3...有很好的参考价值.
💻 C
📖 第 1 页 / 共 3 页
字号:
 			memcpy(haddr, n->ha, dev->addr_len);			read_unlock_bh(&n->lock);			neigh_release(n);			return 0;		}		neigh_release(n);	} else		kfree_skb(skb);	return 1;}/* END OF OBSOLETE FUNCTIONS */int arp_bind_neighbour(struct dst_entry *dst){	struct net_device *dev = dst->dev;	struct neighbour *n = dst->neighbour;	if (dev == NULL)		return -EINVAL;	if (n == NULL) {		u32 nexthop = ((struct rtable*)dst)->rt_gateway;		if (dev->flags&(IFF_LOOPBACK|IFF_POINTOPOINT))			nexthop = 0;		n = __neigh_lookup_errno(#ifdef CONFIG_ATM_CLIP		    dev->type == ARPHRD_ATM ? &clip_tbl :#endif		    &arp_tbl, &nexthop, dev);		if (IS_ERR(n))			return PTR_ERR(n);		dst->neighbour = n;	}	return 0;}/* *	Interface to link layer: send routine and receive handler. *//* *	Create and send an arp packet. If (dest_hw == NULL), we create a broadcast *	message. */void arp_send(int type, int ptype, u32 dest_ip, 	      struct net_device *dev, u32 src_ip, 	      unsigned char *dest_hw, unsigned char *src_hw,	      unsigned char *target_hw){	struct sk_buff *skb;	struct arphdr *arp;	unsigned char *arp_ptr;	/*	 *	No arp on this interface.	 */		if (dev->flags&IFF_NOARP)		return;	/*	 *	Allocate a buffer	 */		skb = alloc_skb(sizeof(struct arphdr)+ 2*(dev->addr_len+4)				+ dev->hard_header_len + 15, GFP_ATOMIC);	if (skb == NULL)		return;	skb_reserve(skb, (dev->hard_header_len+15)&~15);	skb->nh.raw = skb->data;	arp = (struct arphdr *) skb_put(skb,sizeof(struct arphdr) + 2*(dev->addr_len+4));	skb->dev = dev;	skb->protocol = __constant_htons (ETH_P_ARP);	if (src_hw == NULL)		src_hw = dev->dev_addr;	if (dest_hw == NULL)		dest_hw = dev->broadcast;	/*	 *	Fill the device header for the ARP frame	 */	if (dev->hard_header &&	    dev->hard_header(skb,dev,ptype,dest_hw,src_hw,skb->len) < 0)		goto out;	/*	 * Fill out the arp protocol part.	 *	 * The arp hardware type should match the device type, except for FDDI,	 * which (according to RFC 1390) should always equal 1 (Ethernet).	 */	/*	 *	Exceptions everywhere. AX.25 uses the AX.25 PID value not the	 *	DIX code for the protocol. Make these device structure fields.	 */	switch (dev->type) {	default:		arp->ar_hrd = htons(dev->type);		arp->ar_pro = __constant_htons(ETH_P_IP);		break;#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)	case ARPHRD_AX25:		arp->ar_hrd = __constant_htons(ARPHRD_AX25);		arp->ar_pro = __constant_htons(AX25_P_IP);		break;#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)	case ARPHRD_NETROM:		arp->ar_hrd = __constant_htons(ARPHRD_NETROM);		arp->ar_pro = __constant_htons(AX25_P_IP);		break;#endif#endif#ifdef CONFIG_FDDI	case ARPHRD_FDDI:		arp->ar_hrd = __constant_htons(ARPHRD_ETHER);		arp->ar_pro = __constant_htons(ETH_P_IP);		break;#endif#ifdef CONFIG_TR	case ARPHRD_IEEE802_TR:		arp->ar_hrd = __constant_htons(ARPHRD_IEEE802);		arp->ar_pro = __constant_htons(ETH_P_IP);		break;#endif	}	arp->ar_hln = dev->addr_len;	arp->ar_pln = 4;	arp->ar_op = htons(type);	arp_ptr=(unsigned char *)(arp+1);	memcpy(arp_ptr, src_hw, dev->addr_len);	arp_ptr+=dev->addr_len;	memcpy(arp_ptr, &src_ip,4);	arp_ptr+=4;	if (target_hw != NULL)		memcpy(arp_ptr, target_hw, dev->addr_len);	else		memset(arp_ptr, 0, dev->addr_len);	arp_ptr+=dev->addr_len;	memcpy(arp_ptr, &dest_ip, 4);	dev_queue_xmit(skb);	return;out:	kfree_skb(skb);}static void parp_redo(struct sk_buff *skb){	arp_rcv(skb, skb->dev, NULL);}/* *	Receive an arp request by the device layer. */int arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt){	struct arphdr *arp = skb->nh.arph;	unsigned char *arp_ptr= (unsigned char *)(arp+1);	struct rtable *rt;	unsigned char *sha, *tha;	u32 sip, tip;	u16 dev_type = dev->type;	int addr_type;	struct in_device *in_dev = in_dev_get(dev);	struct neighbour *n;/* *	The hardware length of the packet should match the hardware length *	of the device.  Similarly, the hardware types should match.  The *	device should be ARP-able.  Also, if pln is not 4, then the lookup *	is not from an IP number.  We can't currently handle this, so toss *	it.  */  	if (in_dev == NULL ||	    arp->ar_hln != dev->addr_len    || 	    dev->flags & IFF_NOARP ||	    skb->pkt_type == PACKET_OTHERHOST ||	    skb->pkt_type == PACKET_LOOPBACK ||	    arp->ar_pln != 4)		goto out;	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)		goto out_of_mem;	if (skb_is_nonlinear(skb)) {		if (skb_linearize(skb, GFP_ATOMIC) != 0)			goto freeskb;		arp = skb->nh.arph;		arp_ptr= (unsigned char *)(arp+1);	}	switch (dev_type) {	default:			if (arp->ar_pro != __constant_htons(ETH_P_IP))			goto out;		if (htons(dev_type) != arp->ar_hrd)			goto out;		break;#ifdef CONFIG_NET_ETHERNET	case ARPHRD_ETHER:		/*		 * ETHERNET devices will accept ARP hardware types of either		 * 1 (Ethernet) or 6 (IEEE 802.2).		 */		if (arp->ar_hrd != __constant_htons(ARPHRD_ETHER) &&		    arp->ar_hrd != __constant_htons(ARPHRD_IEEE802))			goto out;		if (arp->ar_pro != __constant_htons(ETH_P_IP))			goto out;		break;#endif#ifdef CONFIG_TR	case ARPHRD_IEEE802_TR:		/*		 * Token ring devices will accept ARP hardware types of either		 * 1 (Ethernet) or 6 (IEEE 802.2).		 */		if (arp->ar_hrd != __constant_htons(ARPHRD_ETHER) &&		    arp->ar_hrd != __constant_htons(ARPHRD_IEEE802))			goto out;		if (arp->ar_pro != __constant_htons(ETH_P_IP))			goto out;		break;#endif#ifdef CONFIG_FDDI	case ARPHRD_FDDI:		/*		 * According to RFC 1390, FDDI devices should accept ARP hardware types		 * of 1 (Ethernet).  However, to be more robust, we'll accept hardware		 * types of either 1 (Ethernet) or 6 (IEEE 802.2).		 */		if (arp->ar_hrd != __constant_htons(ARPHRD_ETHER) &&		    arp->ar_hrd != __constant_htons(ARPHRD_IEEE802))			goto out;		if (arp->ar_pro != __constant_htons(ETH_P_IP))			goto out;		break;#endif#ifdef CONFIG_NET_FC	case ARPHRD_IEEE802:		/*		 * According to RFC 2625, Fibre Channel devices (which are IEEE		 * 802 devices) should accept ARP hardware types of 6 (IEEE 802)		 * and 1 (Ethernet).		 */		if (arp->ar_hrd != __constant_htons(ARPHRD_ETHER) &&		    arp->ar_hrd != __constant_htons(ARPHRD_IEEE802))			goto out;		if (arp->ar_pro != __constant_htons(ETH_P_IP))			goto out;		break;#endif#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)	case ARPHRD_AX25:		if (arp->ar_pro != __constant_htons(AX25_P_IP))			goto out;		if (arp->ar_hrd != __constant_htons(ARPHRD_AX25))			goto out;		break;#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)	case ARPHRD_NETROM:		if (arp->ar_pro != __constant_htons(AX25_P_IP))			goto out;		if (arp->ar_hrd != __constant_htons(ARPHRD_NETROM))			goto out;		break;#endif#endif	}	/* Understand only these message types */	if (arp->ar_op != __constant_htons(ARPOP_REPLY) &&	    arp->ar_op != __constant_htons(ARPOP_REQUEST))		goto out;/* *	Extract fields */	sha=arp_ptr;	arp_ptr += dev->addr_len;	memcpy(&sip, arp_ptr, 4);	arp_ptr += 4;	tha=arp_ptr;	arp_ptr += dev->addr_len;	memcpy(&tip, arp_ptr, 4);/*  *	Check for bad requests for 127.x.x.x and requests for multicast *	addresses.  If this is one such, delete it. */	if (LOOPBACK(tip) || MULTICAST(tip))		goto out;/* *     Special case: We must set Frame Relay source Q.922 address */	if (dev_type == ARPHRD_DLCI)		sha = dev->broadcast;/* *  Process entry.  The idea here is we want to send a reply if it is a *  request for us or if it is a request for someone else that we hold *  a proxy for.  We want to add an entry to our cache if it is a reply *  to us or if it is a request for our address.   *  (The assumption for this last is that if someone is requesting our  *  address, they are probably intending to talk to us, so it saves time  *  if we cache their address.  Their address is also probably not in  *  our cache, since ours is not in their cache.) *  *  Putting this another way, we only care about replies if they are to *  us, in which case we add them to the cache.  For requests, we care *  about those for us and those for our proxies.  We reply to both, *  and in the case of requests for us we add the requester to the arp  *  cache. */	/* Special case: IPv4 duplicate address detection packet (RFC2131) */	if (sip == 0) {		if (arp->ar_op == __constant_htons(ARPOP_REQUEST) &&		    inet_addr_type(tip) == RTN_LOCAL)			arp_send(ARPOP_REPLY,ETH_P_ARP,tip,dev,tip,sha,dev->dev_addr,dev->dev_addr);		goto out;	}	if (arp->ar_op == __constant_htons(ARPOP_REQUEST) &&	    ip_route_input(skb, tip, sip, 0, dev) == 0) {		rt = (struct rtable*)skb->dst;		addr_type = rt->rt_type;		if (addr_type == RTN_LOCAL) {			n = neigh_event_ns(&arp_tbl, sha, &sip, dev);			if (n) {				int dont_send = 0;				if (IN_DEV_ARPFILTER(in_dev))					dont_send |= arp_filter(sip,tip,dev); 				if (!dont_send)					arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);				neigh_release(n);			}			goto out;		} else if (IN_DEV_FORWARD(in_dev)) {			if ((rt->rt_flags&RTCF_DNAT) ||			    (addr_type == RTN_UNICAST  && rt->u.dst.dev != dev &&			     (IN_DEV_PROXY_ARP(in_dev) || pneigh_lookup(&arp_tbl, &tip, dev, 0)))) {				n = neigh_event_ns(&arp_tbl, sha, &sip, dev);				if (n)					neigh_release(n);				if (skb->stamp.tv_sec == 0 ||				    skb->pkt_type == PACKET_HOST ||				    in_dev->arp_parms->proxy_delay == 0) {					arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);				} else {					pneigh_enqueue(&arp_tbl, in_dev->arp_parms, skb);					in_dev_put(in_dev);					return 0;				}				goto out;			}		}	}	/* Update our ARP tables */	n = __neigh_lookup(&arp_tbl, &sip, dev, 0);#ifdef CONFIG_IP_ACCEPT_UNSOLICITED_ARP	/* Unsolicited ARP is not accepted by default.	   It is possible, that this option should be enabled for some	   devices (strip is candidate)	 */	if (n == NULL &&	    arp->ar_op == __constant_htons(ARPOP_REPLY) &&	    inet_addr_type(sip) == RTN_UNICAST)		n = __neigh_lookup(&arp_tbl, &sip, dev, -1);#endif	if (n) {		int state = NUD_REACHABLE;		int override = 0;		/* If several different ARP replies follows back-to-back,		   use the FIRST one. It is possible, if several proxy		   agents are active. Taking the first reply prevents		   arp trashing and chooses the fastest router.		 */		if (jiffies - n->updated >= n->parms->locktime)			override = 1;		/* Broadcast replies and request packets		   do not assert neighbour reachability.		 */		if (arp->ar_op != __constant_htons(ARPOP_REPLY) ||		    skb->pkt_type != PACKET_HOST)			state = NUD_STALE;		neigh_update(n, sha, state, override, 1);		neigh_release(n);	}out:	if (in_dev)		in_dev_put(in_dev);freeskb:

⌨️ 快捷键说明

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