📄 mkudp.c
字号:
/* * mkudp.c * Joris van Rantwijk, May 2001. */#include <linux/socket.h>#include <linux/in.h>#include <linux/ip.h>#include <linux/udp.h>#include "mkudp.h"#ifdef __i386__/* i386 assembler version from asm-i386/checksum.h *//* * This is a version of ip_compute_csum() optimized for IP headers, * which always checksum on 4 octet boundaries. * * By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by * Arnt Gulbrandsen. */static unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl) { unsigned int sum; __asm__ __volatile__(" movl (%1), %0 subl $4, %2 jbe 2f addl 4(%1), %0 adcl 8(%1), %0 adcl 12(%1), %01: adcl 16(%1), %0 lea 4(%1), %1 decl %2 jne 1b adcl $0, %0 movl %0, %2 shrl $16, %0 addw %w2, %w0 adcl $0, %0 notl %02: " /* Since the input registers which are loaded with iph and ipl are modified, we must also specify them as outputs, or gcc will assume they contain their original values. */ : "=r" (sum), "=r" (iph), "=r" (ihl) : "1" (iph), "2" (ihl)); return(sum);}#endif#ifdef __ppc__static unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl){ unsigned int sum, dummy; __asm__ __volatile__ ("/* * ip_fast_csum(buf, len) -- Optimized for IP header * len is in words and is always >= 5. */ lwz %0,0(%1) lwzu %3,4(%1) addic. %2,%2,-2 addc %0,%0,%3 mtctr %2 ble- 2f1: lwzu %2,4(%1) adde %0,%0,%2 bdnz 1b addze %0,%0 /* add in final carry */ rlwinm %1,%0,16,0,31 /* fold two halves together */ add %0,%0,%1 not %0,%0 srwi %0,%0,162: " : "=r" (sum), "=r" (iph), "=r" (ihl), "=r" (dummy) : "1" (iph), "2" (ihl) ); return sum;}#if 0/* * Compute checksum of TCP or UDP pseudo-header: * csum_tcpudp_magic(saddr, daddr, len, proto, sum) */ _GLOBAL(csum_tcpudp_magic) rlwimi r5,r6,16,0,15 /* put proto in upper half of len */ addc r0,r3,r4 /* add 4 32-bit words together */ adde r0,r0,r5 adde r0,r0,r7 addze r0,r0 /* add in final carry */ rlwinm r3,r0,16,0,31 /* fold two halves together */ add r3,r0,r3 not r3,r3 srwi r3,r3,16 blr/* * computes the checksum of a memory block at buff, length len, * and adds in "sum" (32-bit) * * csum_partial(buff, len, sum) */_GLOBAL(csum_partial) addic r0,r5,0 subi r3,r3,4 srwi. r6,r4,2 beq 3f /* if we're doing < 4 bytes */ andi. r5,r3,2 /* Align buffer to longword boundary */ beq+ 1f lhz r5,4(r3) /* do 2 bytes to get aligned */ addi r3,r3,2 subi r4,r4,2 addc r0,r0,r5 srwi. r6,r4,2 /* # words to do */ beq 3f1: mtctr r62: lwzu r5,4(r3) /* the bdnz has zero overhead, so it should */ adde r0,r0,r5 /* be unnecessary to unroll this loop */ bdnz 2b andi. r4,r4,33: cmpi 0,r4,2 blt+ 4f lhz r5,4(r3) addi r3,r3,2 subi r4,r4,2 adde r0,r0,r54: cmpi 0,r4,1 bne+ 5f lbz r5,4(r3) slwi r5,r5,8 /* Upper byte of word */ adde r0,r0,r55: addze r3,r0 /* add in final carry */ blr#endif#endif#if 0/* generic C version */static inline unsigned shortip_fast_csum(unsigned char * iph, unsigned int ihl){ unsigned short *ip = (unsigned short *) iph; unsigned long sum = 0; int i; for (i = 0; i < 2*ihl; i++) sum += ip[i]; sum = (sum & 0x0000ffff) + (sum >> 16); sum = (sum & 0x0000ffff) + (sum >> 16); return ~sum;}#endif/* * Construct the IP and UDP headers for an UDP/IP datagram. * packetbuf points to the start of the resulting packet with * exactly UPD_IP_HEADER_LEN bytes room to put the header, followed * by dlen bytes of application data. * Fragmentation is not supported, the datagram must fit in a single packet. * UDP checksumming is not supported. */void build_udp_ip_header(unsigned char *packetbuf, unsigned int dlen, const struct sockaddr_in *saddr, const struct sockaddr_in *daddr){ struct iphdr *iph = (struct iphdr *) packetbuf; struct udphdr *uh = (struct udphdr *) (packetbuf + IP_HEADER_LEN); static int ip_ident_hack = 1; /* Build IP header */ iph->version = 4; iph->ihl = 5; iph->tos = 0; iph->tot_len = htons(dlen + UDP_IP_HEADER_LEN); iph->id = htons(ip_ident_hack++); /* Ugly */ iph->frag_off = 0; iph->ttl = IP_DEFAULT_TTL; iph->protocol = IPPROTO_UDP; iph->saddr = saddr->sin_addr.s_addr; iph->daddr = daddr->sin_addr.s_addr; iph->check = 0; iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); /* Build UPD header */ uh->source = saddr->sin_port; uh->dest = daddr->sin_port; uh->len = htons(dlen + sizeof(struct udphdr)); uh->check = 0;}/* end */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -