struct udpiphdr *udp_read(void) { int len; char *ptr; struct ether_header *eptr; for ( ; ; ) { // 从分组捕获设备获取下一个分组 ptr = next_pcap(&len); switch (datalink) { case DLT_NULL: // loopback header = 4 bytes return(udp_check(ptr + 4, len - 4)); case DLT_EN10MB: eptr = (struct ether_header *) ptr; if (ntohs(eptr->ether_type) != ETHERTYPE_IP) { err_quit("Ethernet type %x not IP", ntohs(eptr->ether_type)); } return(udp_check(ptr + 14, len - 14)); case DLT_SLIP: // SLIP header = 24 bytes return(udp_check(ptr + 24, len - 24)); case DLT_PPP: // PPP header = 24 bytes return(udp_check(ptr + 24, len - 24)); default: err_quit("unsupported datalink (%d)", datalink); } } }
// This is a very weird function, look at udpCheckReceiveFork() in matlab.c for the "why" int udpmsg_receive(udpmsg *packet) { char recv_buf[MAXMSGLENGTH+10]; char senderIP[16]; // "xxx.xxx.xxx.xxx\0" int ret = 0; if(udp_check(0)) { udp_read(recv_buf, sizeof(recv_buf), senderIP); // printf("%s\n", senderIP); // First if clause determines whether message is from Psychtoolbox if (!strcmp(senderIP, macIP)) { if(strlen(recv_buf)>10 && recv_buf[9]==' ' && strcmp(recv_buf,last_recv)!=0) { strcpy(last_recv, recv_buf); strncpy(packet->id, recv_buf, 9); packet->id[9] = 0; strcpy(packet->msg, recv_buf+10); if (strcmp(packet->msg,"RECEIVED")==0) packet->received = 1; else if (strcmp(packet->msg,"EXECUTED")==0) packet->executed = 1; else { /* if it is a new message confirm its receipt */ strcpy(recv_buf+10, "RECEIVED"); udp_send(recv_buf, macIP); } ret = 1; } } } return ret; }
int udp_send(struct netdev *nd, struct sin *from, struct sin *to, struct buflist *data) { struct buflist bl, *blp; struct udphdr udp; int size = 0; bl.data = &udp; bl.size = sizeof(udp); bl.next = data; for (blp = &bl; blp; blp = blp->next) size += blp->size; udp.udp_source = from->sin_port; udp.udp_dest = to->sin_port; udp.udp_length = htons(size); udp.udp_check = 0; udp.udp_check = udp_check(&udp, from, to, &bl, size); return ip_send(nd, 0x11, from->sin_addr, to->sin_addr, &bl); }
int udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, __u32 daddr, unsigned short len, __u32 saddr, int redo, struct inet_protocol *protocol) { struct sock *sk; struct udphdr *uh; unsigned short ulen; int addr_type; /* * If we're doing a "redo" (the socket was busy last time * around), we can just queue the packet now.. */ if (redo) { udp_queue_rcv_skb(skb->sk, skb); return 0; } /* * First time through the loop.. Do all the setup stuff * (including finding out the socket we go to etc) */ addr_type = IS_MYADDR; if(!dev || dev->pa_addr!=daddr) addr_type=ip_chk_addr(daddr); /* * Get the header. */ uh = (struct udphdr *) skb->h.uh; ip_statistics.IpInDelivers++; /* * Validate the packet and the UDP length. */ ulen = ntohs(uh->len); if (ulen > len || len < sizeof(*uh) || ulen < sizeof(*uh)) { NETDEBUG(printk("UDP: short packet: %d/%d\n", ulen, len)); udp_statistics.UdpInErrors++; kfree_skb(skb, FREE_WRITE); return(0); } /* RFC1122 warning: According to 4.1.3.6, we MUST discard any */ /* datagram which has an invalid source address, either here or */ /* in IP. */ /* Right now, IP isn't doing it, and neither is UDP. It's on the */ /* FIXME list for IP, though, so I wouldn't worry about it. */ /* (That's the Right Place to do it, IMHO.) -- MS */ if (uh->check && ( ( (skb->ip_summed == CHECKSUM_HW) && udp_check(uh, len, saddr, daddr, skb->csum ) ) || ( (skb->ip_summed == CHECKSUM_NONE) && udp_check(uh, len, saddr, daddr,csum_partial((char*)uh, len, 0))) /* skip if CHECKSUM_UNNECESSARY */ ) ) { /* <*****@*****.**> wants to know, who sent it, to go and stomp on the garbage sender... */ /* RFC1122: OK. Discards the bad packet silently (as far as */ /* the network is concerned, anyway) as per 4.1.3.4 (MUST). */ NETDEBUG(printk("UDP: bad checksum. From %08lX:%d to %08lX:%d ulen %d\n", ntohl(saddr),ntohs(uh->source), ntohl(daddr),ntohs(uh->dest), ulen)); udp_statistics.UdpInErrors++; kfree_skb(skb, FREE_WRITE); return(0); } /* * These are supposed to be switched. */ skb->daddr = saddr; skb->saddr = daddr; len=ulen; skb->dev = dev; skb_trim(skb,len); #ifdef CONFIG_IP_MULTICAST if (addr_type==IS_BROADCAST || addr_type==IS_MULTICAST) return udp_v4_mcast_deliver(skb, uh, saddr, daddr); #endif #ifdef CONFIG_IP_TRANSPARENT_PROXY if(skb->redirport) sk = udp_v4_proxy_lookup(saddr, uh->source, daddr, uh->dest, dev->pa_addr, skb->redirport, dev); else #endif sk = udp_v4_lookup(saddr, uh->source, daddr, uh->dest, dev); if (sk == NULL) { udp_statistics.UdpNoPorts++; if (addr_type != IS_BROADCAST && addr_type != IS_MULTICAST) { icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev); } /* * Hmm. We got an UDP broadcast to a port to which we * don't wanna listen. Ignore it. */ skb->sk = NULL; kfree_skb(skb, FREE_WRITE); return(0); } udp_deliver(sk, skb); return 0; }