diff options
author | Baruch Siach <baruch@tkos.co.il> | 2011-09-07 17:52:37 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2011-09-07 17:55:40 +0200 |
commit | e8f36330d9bb27f9f7e66aa6f01ff92c07d86f62 (patch) | |
tree | 863018163a166cc690902d8027a3f04f9f812dd3 | |
parent | 8c84f7545cf08925edb23d94d9f6519b338267c6 (diff) | |
download | busybox-w32-e8f36330d9bb27f9f7e66aa6f01ff92c07d86f62.tar.gz busybox-w32-e8f36330d9bb27f9f7e66aa6f01ff92c07d86f62.tar.bz2 busybox-w32-e8f36330d9bb27f9f7e66aa6f01ff92c07d86f62.zip |
networking: consolidate the IP checksum code. -129 bytes.
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | include/libbb.h | 1 | ||||
-rw-r--r-- | libbb/Kbuild.src | 6 | ||||
-rw-r--r-- | libbb/inet_cksum.c | 32 | ||||
-rw-r--r-- | networking/ping.c | 31 | ||||
-rw-r--r-- | networking/traceroute.c | 35 | ||||
-rw-r--r-- | networking/udhcp/dhcpc.c | 4 | ||||
-rw-r--r-- | networking/udhcp/packet.c | 34 |
7 files changed, 48 insertions, 95 deletions
diff --git a/include/libbb.h b/include/libbb.h index 1ca448930..f60f4278b 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -640,6 +640,7 @@ ssize_t recv_from_to(int fd, void *buf, size_t len, int flags, | |||
640 | struct sockaddr *to, | 640 | struct sockaddr *to, |
641 | socklen_t sa_size) FAST_FUNC; | 641 | socklen_t sa_size) FAST_FUNC; |
642 | 642 | ||
643 | uint16_t inet_cksum(uint16_t *addr, int len) FAST_FUNC; | ||
643 | 644 | ||
644 | char *xstrdup(const char *s) FAST_FUNC RETURNS_MALLOC; | 645 | char *xstrdup(const char *s) FAST_FUNC RETURNS_MALLOC; |
645 | char *xstrndup(const char *s, int n) FAST_FUNC RETURNS_MALLOC; | 646 | char *xstrndup(const char *s, int n) FAST_FUNC RETURNS_MALLOC; |
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src index 875d02456..335b34128 100644 --- a/libbb/Kbuild.src +++ b/libbb/Kbuild.src | |||
@@ -166,6 +166,12 @@ lib-$(CONFIG_IOSTAT) += get_cpu_count.o | |||
166 | lib-$(CONFIG_MPSTAT) += get_cpu_count.o | 166 | lib-$(CONFIG_MPSTAT) += get_cpu_count.o |
167 | lib-$(CONFIG_POWERTOP) += get_cpu_count.o | 167 | lib-$(CONFIG_POWERTOP) += get_cpu_count.o |
168 | 168 | ||
169 | lib-$(CONFIG_PING) += inet_cksum.o | ||
170 | lib-$(CONFIG_TRACEROUTE) += inet_cksum.o | ||
171 | lib-$(CONFIG_TRACEROUTE6) += inet_cksum.o | ||
172 | lib-$(CONFIG_UDHCPC) += inet_cksum.o | ||
173 | lib-$(CONFIG_UDHCPD) += inet_cksum.o | ||
174 | |||
169 | # We shouldn't build xregcomp.c if we don't need it - this ensures we don't | 175 | # We shouldn't build xregcomp.c if we don't need it - this ensures we don't |
170 | # require regex.h to be in the include dir even if we don't need it thereby | 176 | # require regex.h to be in the include dir even if we don't need it thereby |
171 | # allowing us to build busybox even if uclibc regex support is disabled. | 177 | # allowing us to build busybox even if uclibc regex support is disabled. |
diff --git a/libbb/inet_cksum.c b/libbb/inet_cksum.c new file mode 100644 index 000000000..31bf8c4d9 --- /dev/null +++ b/libbb/inet_cksum.c | |||
@@ -0,0 +1,32 @@ | |||
1 | /* | ||
2 | * Checksum routine for Internet Protocol family headers (C Version) | ||
3 | * | ||
4 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
5 | */ | ||
6 | |||
7 | #include "libbb.h" | ||
8 | |||
9 | uint16_t FAST_FUNC inet_cksum(uint16_t *addr, int nleft) | ||
10 | { | ||
11 | /* | ||
12 | * Our algorithm is simple, using a 32 bit accumulator, | ||
13 | * we add sequential 16 bit words to it, and at the end, fold | ||
14 | * back all the carry bits from the top 16 bits into the lower | ||
15 | * 16 bits. | ||
16 | */ | ||
17 | unsigned sum = 0; | ||
18 | while (nleft > 1) { | ||
19 | sum += *addr++; | ||
20 | nleft -= 2; | ||
21 | } | ||
22 | |||
23 | /* Mop up an odd byte, if necessary */ | ||
24 | if (nleft) | ||
25 | sum += *(uint8_t*)addr; | ||
26 | |||
27 | /* Add back carry outs from top 16 bits to low 16 bits */ | ||
28 | sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ | ||
29 | sum += (sum >> 16); /* add carry */ | ||
30 | |||
31 | return (uint16_t)~sum; | ||
32 | } | ||
diff --git a/networking/ping.c b/networking/ping.c index efd4f210b..a1fd9dfb1 100644 --- a/networking/ping.c +++ b/networking/ping.c | |||
@@ -149,31 +149,6 @@ enum { | |||
149 | PINGINTERVAL = 1, /* 1 second */ | 149 | PINGINTERVAL = 1, /* 1 second */ |
150 | }; | 150 | }; |
151 | 151 | ||
152 | /* Common routines */ | ||
153 | |||
154 | static int in_cksum(unsigned short *buf, int sz) | ||
155 | { | ||
156 | int nleft = sz; | ||
157 | int sum = 0; | ||
158 | unsigned short *w = buf; | ||
159 | unsigned short ans = 0; | ||
160 | |||
161 | while (nleft > 1) { | ||
162 | sum += *w++; | ||
163 | nleft -= 2; | ||
164 | } | ||
165 | |||
166 | if (nleft == 1) { | ||
167 | *(unsigned char *) (&ans) = *(unsigned char *) w; | ||
168 | sum += ans; | ||
169 | } | ||
170 | |||
171 | sum = (sum >> 16) + (sum & 0xFFFF); | ||
172 | sum += (sum >> 16); | ||
173 | ans = ~sum; | ||
174 | return ans; | ||
175 | } | ||
176 | |||
177 | #if !ENABLE_FEATURE_FANCY_PING | 152 | #if !ENABLE_FEATURE_FANCY_PING |
178 | 153 | ||
179 | /* Simple version */ | 154 | /* Simple version */ |
@@ -201,7 +176,7 @@ static void ping4(len_and_sockaddr *lsa) | |||
201 | pkt = (struct icmp *) G.packet; | 176 | pkt = (struct icmp *) G.packet; |
202 | memset(pkt, 0, sizeof(G.packet)); | 177 | memset(pkt, 0, sizeof(G.packet)); |
203 | pkt->icmp_type = ICMP_ECHO; | 178 | pkt->icmp_type = ICMP_ECHO; |
204 | pkt->icmp_cksum = in_cksum((unsigned short *) pkt, sizeof(G.packet)); | 179 | pkt->icmp_cksum = inet_cksum((uint16_t *) pkt, sizeof(G.packet)); |
205 | 180 | ||
206 | xsendto(pingsock, G.packet, DEFDATALEN + ICMP_MINLEN, &lsa->u.sa, lsa->len); | 181 | xsendto(pingsock, G.packet, DEFDATALEN + ICMP_MINLEN, &lsa->u.sa, lsa->len); |
207 | 182 | ||
@@ -493,7 +468,7 @@ static void sendping4(int junk UNUSED_PARAM) | |||
493 | /* No hton: we'll read it back on the same machine */ | 468 | /* No hton: we'll read it back on the same machine */ |
494 | *(uint32_t*)&pkt->icmp_dun = monotonic_us(); | 469 | *(uint32_t*)&pkt->icmp_dun = monotonic_us(); |
495 | 470 | ||
496 | pkt->icmp_cksum = in_cksum((unsigned short *) pkt, datalen + ICMP_MINLEN); | 471 | pkt->icmp_cksum = inet_cksum((uint16_t *) pkt, datalen + ICMP_MINLEN); |
497 | 472 | ||
498 | sendping_tail(sendping4, ICMP_MINLEN); | 473 | sendping_tail(sendping4, ICMP_MINLEN); |
499 | } | 474 | } |
@@ -512,7 +487,7 @@ static void sendping6(int junk UNUSED_PARAM) | |||
512 | /*if (datalen >= 4)*/ | 487 | /*if (datalen >= 4)*/ |
513 | *(uint32_t*)(&pkt->icmp6_data8[4]) = monotonic_us(); | 488 | *(uint32_t*)(&pkt->icmp6_data8[4]) = monotonic_us(); |
514 | 489 | ||
515 | //TODO? pkt->icmp_cksum = in_cksum(...); | 490 | //TODO? pkt->icmp_cksum = inet_cksum(...); |
516 | 491 | ||
517 | sendping_tail(sendping6, sizeof(struct icmp6_hdr)); | 492 | sendping_tail(sendping6, sizeof(struct icmp6_hdr)); |
518 | } | 493 | } |
diff --git a/networking/traceroute.c b/networking/traceroute.c index c32103519..d197e5410 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c | |||
@@ -418,39 +418,6 @@ wait_for_reply(len_and_sockaddr *from_lsa, struct sockaddr *to, unsigned *timest | |||
418 | return read_len; | 418 | return read_len; |
419 | } | 419 | } |
420 | 420 | ||
421 | /* | ||
422 | * Checksum routine for Internet Protocol family headers (C Version) | ||
423 | */ | ||
424 | static uint16_t | ||
425 | in_cksum(uint16_t *addr, int len) | ||
426 | { | ||
427 | int nleft = len; | ||
428 | uint16_t *w = addr; | ||
429 | uint16_t answer; | ||
430 | int sum = 0; | ||
431 | |||
432 | /* | ||
433 | * Our algorithm is simple, using a 32 bit accumulator (sum), | ||
434 | * we add sequential 16 bit words to it, and at the end, fold | ||
435 | * back all the carry bits from the top 16 bits into the lower | ||
436 | * 16 bits. | ||
437 | */ | ||
438 | while (nleft > 1) { | ||
439 | sum += *w++; | ||
440 | nleft -= 2; | ||
441 | } | ||
442 | |||
443 | /* mop up an odd byte, if necessary */ | ||
444 | if (nleft == 1) | ||
445 | sum += *(unsigned char *)w; | ||
446 | |||
447 | /* add back carry outs from top 16 bits to low 16 bits */ | ||
448 | sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ | ||
449 | sum += (sum >> 16); /* add carry */ | ||
450 | answer = ~sum; /* truncate to 16 bits */ | ||
451 | return answer; | ||
452 | } | ||
453 | |||
454 | static void | 421 | static void |
455 | send_probe(int seq, int ttl) | 422 | send_probe(int seq, int ttl) |
456 | { | 423 | { |
@@ -477,7 +444,7 @@ send_probe(int seq, int ttl) | |||
477 | 444 | ||
478 | /* Always calculate checksum for icmp packets */ | 445 | /* Always calculate checksum for icmp packets */ |
479 | outicmp->icmp_cksum = 0; | 446 | outicmp->icmp_cksum = 0; |
480 | outicmp->icmp_cksum = in_cksum((uint16_t *)outicmp, | 447 | outicmp->icmp_cksum = inet_cksum((uint16_t *)outicmp, |
481 | packlen - (sizeof(*outip) + optlen)); | 448 | packlen - (sizeof(*outip) + optlen)); |
482 | if (outicmp->icmp_cksum == 0) | 449 | if (outicmp->icmp_cksum == 0) |
483 | outicmp->icmp_cksum = 0xffff; | 450 | outicmp->icmp_cksum = 0xffff; |
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 4d755e6b8..3be09f4d7 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -739,7 +739,7 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) | |||
739 | /* verify IP checksum */ | 739 | /* verify IP checksum */ |
740 | check = packet.ip.check; | 740 | check = packet.ip.check; |
741 | packet.ip.check = 0; | 741 | packet.ip.check = 0; |
742 | if (check != udhcp_checksum(&packet.ip, sizeof(packet.ip))) { | 742 | if (check != inet_cksum((uint16_t *)&packet.ip, sizeof(packet.ip))) { |
743 | log1("Bad IP header checksum, ignoring"); | 743 | log1("Bad IP header checksum, ignoring"); |
744 | return -2; | 744 | return -2; |
745 | } | 745 | } |
@@ -750,7 +750,7 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) | |||
750 | packet.ip.tot_len = packet.udp.len; /* yes, this is needed */ | 750 | packet.ip.tot_len = packet.udp.len; /* yes, this is needed */ |
751 | check = packet.udp.check; | 751 | check = packet.udp.check; |
752 | packet.udp.check = 0; | 752 | packet.udp.check = 0; |
753 | if (check && check != udhcp_checksum(&packet, bytes)) { | 753 | if (check && check != inet_cksum((uint16_t *)&packet, bytes)) { |
754 | log1("Packet with bad UDP checksum received, ignoring"); | 754 | log1("Packet with bad UDP checksum received, ignoring"); |
755 | return -2; | 755 | return -2; |
756 | } | 756 | } |
diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c index 66b42c5e1..4d5ff0676 100644 --- a/networking/udhcp/packet.c +++ b/networking/udhcp/packet.c | |||
@@ -129,35 +129,6 @@ int FAST_FUNC udhcp_recv_kernel_packet(struct dhcp_packet *packet, int fd) | |||
129 | return bytes; | 129 | return bytes; |
130 | } | 130 | } |
131 | 131 | ||
132 | uint16_t FAST_FUNC udhcp_checksum(void *addr, int count) | ||
133 | { | ||
134 | /* Compute Internet Checksum for "count" bytes | ||
135 | * beginning at location "addr". | ||
136 | */ | ||
137 | int32_t sum = 0; | ||
138 | uint16_t *source = (uint16_t *) addr; | ||
139 | |||
140 | while (count > 1) { | ||
141 | /* This is the inner loop */ | ||
142 | sum += *source++; | ||
143 | count -= 2; | ||
144 | } | ||
145 | |||
146 | /* Add left-over byte, if any */ | ||
147 | if (count > 0) { | ||
148 | /* Make sure that the left-over byte is added correctly both | ||
149 | * with little and big endian hosts */ | ||
150 | uint16_t tmp = 0; | ||
151 | *(uint8_t*)&tmp = *(uint8_t*)source; | ||
152 | sum += tmp; | ||
153 | } | ||
154 | /* Fold 32-bit sum to 16 bits */ | ||
155 | while (sum >> 16) | ||
156 | sum = (sum & 0xffff) + (sum >> 16); | ||
157 | |||
158 | return ~sum; | ||
159 | } | ||
160 | |||
161 | /* Construct a ip/udp header for a packet, send packet */ | 132 | /* Construct a ip/udp header for a packet, send packet */ |
162 | int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, | 133 | int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, |
163 | uint32_t source_nip, int source_port, | 134 | uint32_t source_nip, int source_port, |
@@ -212,13 +183,14 @@ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt, | |||
212 | packet.udp.len = htons(UDP_DHCP_SIZE - padding); | 183 | packet.udp.len = htons(UDP_DHCP_SIZE - padding); |
213 | /* for UDP checksumming, ip.len is set to UDP packet len */ | 184 | /* for UDP checksumming, ip.len is set to UDP packet len */ |
214 | packet.ip.tot_len = packet.udp.len; | 185 | packet.ip.tot_len = packet.udp.len; |
215 | packet.udp.check = udhcp_checksum(&packet, IP_UDP_DHCP_SIZE - padding); | 186 | packet.udp.check = inet_cksum((uint16_t *)&packet, |
187 | IP_UDP_DHCP_SIZE - padding); | ||
216 | /* but for sending, it is set to IP packet len */ | 188 | /* but for sending, it is set to IP packet len */ |
217 | packet.ip.tot_len = htons(IP_UDP_DHCP_SIZE - padding); | 189 | packet.ip.tot_len = htons(IP_UDP_DHCP_SIZE - padding); |
218 | packet.ip.ihl = sizeof(packet.ip) >> 2; | 190 | packet.ip.ihl = sizeof(packet.ip) >> 2; |
219 | packet.ip.version = IPVERSION; | 191 | packet.ip.version = IPVERSION; |
220 | packet.ip.ttl = IPDEFTTL; | 192 | packet.ip.ttl = IPDEFTTL; |
221 | packet.ip.check = udhcp_checksum(&packet.ip, sizeof(packet.ip)); | 193 | packet.ip.check = inet_cksum((uint16_t *)&packet.ip, sizeof(packet.ip)); |
222 | 194 | ||
223 | udhcp_dump_packet(dhcp_pkt); | 195 | udhcp_dump_packet(dhcp_pkt); |
224 | result = sendto(fd, &packet, IP_UDP_DHCP_SIZE - padding, /*flags:*/ 0, | 196 | result = sendto(fd, &packet, IP_UDP_DHCP_SIZE - padding, /*flags:*/ 0, |