aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>2011-01-04 19:52:10 +0700
committerNguyễn Thái Ngọc Duy <pclouds@gmail.com>2011-01-04 19:52:10 +0700
commit8cef222175855ae08f3768a5586b00650240403d (patch)
tree224364dc08e460fea425df95fc45e1cbc9bbbd96
parent9fab97cbb70312170739e29a5fbbbe072f07bb78 (diff)
parentcbfeaac7afe31323d46c52da3b98a949232d708e (diff)
downloadbusybox-w32-8cef222175855ae08f3768a5586b00650240403d.tar.gz
busybox-w32-8cef222175855ae08f3768a5586b00650240403d.tar.bz2
busybox-w32-8cef222175855ae08f3768a5586b00650240403d.zip
Merge commit '6722737ece4b8db3e30b53aef8f981f53db1621e^'
-rw-r--r--coreutils/fsync.c2
-rw-r--r--coreutils/stat.c12
-rw-r--r--coreutils/tail.c1
-rw-r--r--editors/patch.c25
-rw-r--r--include/libbb.h54
-rw-r--r--include/usage.src.h94
-rw-r--r--libbb/hash_md5_sha.c957
-rw-r--r--libbb/safe_strncpy.c11
-rw-r--r--loginutils/add-remove-shell.c135
-rw-r--r--miscutils/crond.c2
-rw-r--r--miscutils/nandwrite.c12
-rw-r--r--networking/nbd-client.c2
-rw-r--r--networking/ntpd.c10
-rw-r--r--networking/udhcp/common.c7
-rw-r--r--networking/udhcp/common.h6
-rw-r--r--networking/udhcp/dhcpc.c294
-rw-r--r--networking/udhcp/dhcpd.c12
-rw-r--r--networking/udhcp/packet.c8
-rw-r--r--procps/pmap.c4
-rw-r--r--procps/smemcap.c3
-rwxr-xr-xscripts/mkmakefile5
-rw-r--r--sysklogd/klogd.c19
-rw-r--r--util-linux/dmesg.c19
23 files changed, 942 insertions, 752 deletions
diff --git a/coreutils/fsync.c b/coreutils/fsync.c
index d1fe2b584..b8b463cd1 100644
--- a/coreutils/fsync.c
+++ b/coreutils/fsync.c
@@ -27,7 +27,7 @@ int fsync_main(int argc UNUSED_PARAM, char **argv)
27 27
28 status = EXIT_SUCCESS; 28 status = EXIT_SUCCESS;
29 do { 29 do {
30 int fd = open3_or_warn(*argv, O_NOATIME | O_NOCTTY | O_RDONLY, 0); 30 int fd = open_or_warn(*argv, O_NOATIME | O_NOCTTY | O_RDONLY);
31 31
32 if (fd == -1) { 32 if (fd == -1) {
33 status = EXIT_FAILURE; 33 status = EXIT_FAILURE;
diff --git a/coreutils/stat.c b/coreutils/stat.c
index 777197292..d176d07ea 100644
--- a/coreutils/stat.c
+++ b/coreutils/stat.c
@@ -247,14 +247,12 @@ static void FAST_FUNC print_stat(char *pformat, const char m,
247 strcat(pformat, "lu"); 247 strcat(pformat, "lu");
248 printf(pformat, (unsigned long) statbuf->st_uid); 248 printf(pformat, (unsigned long) statbuf->st_uid);
249 } else if (m == 'U') { 249 } else if (m == 'U') {
250 setpwent();
251 pw_ent = getpwuid(statbuf->st_uid); 250 pw_ent = getpwuid(statbuf->st_uid);
252 printfs(pformat, (pw_ent != NULL) ? pw_ent->pw_name : "UNKNOWN"); 251 printfs(pformat, (pw_ent != NULL) ? pw_ent->pw_name : "UNKNOWN");
253 } else if (m == 'g') { 252 } else if (m == 'g') {
254 strcat(pformat, "lu"); 253 strcat(pformat, "lu");
255 printf(pformat, (unsigned long) statbuf->st_gid); 254 printf(pformat, (unsigned long) statbuf->st_gid);
256 } else if (m == 'G') { 255 } else if (m == 'G') {
257 setgrent();
258 gw_ent = getgrgid(statbuf->st_gid); 256 gw_ent = getgrgid(statbuf->st_gid);
259 printfs(pformat, (gw_ent != NULL) ? gw_ent->gr_name : "UNKNOWN"); 257 printfs(pformat, (gw_ent != NULL) ? gw_ent->gr_name : "UNKNOWN");
260 } else if (m == 't') { 258 } else if (m == 't') {
@@ -591,20 +589,20 @@ static bool do_stat(const char *filename, const char *format)
591# endif 589# endif
592 } else { 590 } else {
593 char *linkname = NULL; 591 char *linkname = NULL;
594
595 struct passwd *pw_ent; 592 struct passwd *pw_ent;
596 struct group *gw_ent; 593 struct group *gw_ent;
597 setgrent(); 594
598 gw_ent = getgrgid(statbuf.st_gid); 595 gw_ent = getgrgid(statbuf.st_gid);
599 setpwent();
600 pw_ent = getpwuid(statbuf.st_uid); 596 pw_ent = getpwuid(statbuf.st_uid);
601 597
602 if (S_ISLNK(statbuf.st_mode)) 598 if (S_ISLNK(statbuf.st_mode))
603 linkname = xmalloc_readlink_or_warn(filename); 599 linkname = xmalloc_readlink_or_warn(filename);
604 if (linkname) 600 if (linkname) {
605 printf(" File: '%s' -> '%s'\n", filename, linkname); 601 printf(" File: '%s' -> '%s'\n", filename, linkname);
606 else 602 free(linkname);
603 } else {
607 printf(" File: '%s'\n", filename); 604 printf(" File: '%s'\n", filename);
605 }
608 606
609 printf(" Size: %-10llu\tBlocks: %-10llu IO Block: %-6lu %s\n" 607 printf(" Size: %-10llu\tBlocks: %-10llu IO Block: %-6lu %s\n"
610 "Device: %llxh/%llud\tInode: %-10llu Links: %-5lu", 608 "Device: %llxh/%llud\tInode: %-10llu Links: %-5lu",
diff --git a/coreutils/tail.c b/coreutils/tail.c
index 44698f304..df881a37a 100644
--- a/coreutils/tail.c
+++ b/coreutils/tail.c
@@ -346,6 +346,7 @@ int tail_main(int argc, char **argv)
346 } 346 }
347 if (ENABLE_FEATURE_CLEAN_UP) { 347 if (ENABLE_FEATURE_CLEAN_UP) {
348 free(fds); 348 free(fds);
349 free(tailbuf);
349 } 350 }
350 return G.status; 351 return G.status;
351} 352}
diff --git a/editors/patch.c b/editors/patch.c
index 66a9474fe..fff06907f 100644
--- a/editors/patch.c
+++ b/editors/patch.c
@@ -17,7 +17,6 @@
17 * -o outfile output here instead of in place 17 * -o outfile output here instead of in place
18 * -r rejectfile write rejected hunks to this file 18 * -r rejectfile write rejected hunks to this file
19 * 19 *
20 * -E remove empty files --remove-empty-files
21 * -f force (no questions asked) 20 * -f force (no questions asked)
22 * -F fuzz (number, default 2) 21 * -F fuzz (number, default 2)
23 * [file] which file to patch 22 * [file] which file to patch
@@ -42,7 +41,7 @@ config PATCH
42 hunks to stderr, and exits with nonzero status if any hunks fail. 41 hunks to stderr, and exits with nonzero status if any hunks fail.
43 42
44 A file compared against /dev/null (or with a date <= the epoch) is 43 A file compared against /dev/null (or with a date <= the epoch) is
45 created/deleted as appropriate. 44 created or deleted if -E or --remove-empty-files set.
46*/ 45*/
47#include "libbb.h" 46#include "libbb.h"
48 47
@@ -243,15 +242,16 @@ struct globals {
243} while (0) 242} while (0)
244 243
245 244
246#define FLAG_STR "Rup:i:Nx" 245#define FLAG_STR "Rup:i:NEx"
247/* FLAG_REVERSE must be == 1! Code uses this fact. */ 246/* FLAG_REVERSE must be == 1! Code uses this fact. */
248#define FLAG_REVERSE (1 << 0) 247#define FLAG_REVERSE (1 << 0)
249#define FLAG_u (1 << 1) 248#define FLAG_u (1 << 1)
250#define FLAG_PATHLEN (1 << 2) 249#define FLAG_PATHLEN (1 << 2)
251#define FLAG_INPUT (1 << 3) 250#define FLAG_INPUT (1 << 3)
252#define FLAG_IGNORE (1 << 4) 251#define FLAG_IGNORE (1 << 4)
252#define FLAG_RMEMPTY (1 << 5)
253//non-standard: 253//non-standard:
254#define FLAG_DEBUG (1 << 5) 254#define FLAG_DEBUG (1 << 6)
255 255
256// Dispose of a line of input, either by writing it out or discarding it. 256// Dispose of a line of input, either by writing it out or discarding it.
257 257
@@ -551,7 +551,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
551 551
552 // If this is the first hunk, open the file. 552 // If this is the first hunk, open the file.
553 if (TT.filein == -1) { 553 if (TT.filein == -1) {
554 int oldsum, newsum, del = 0; 554 int oldsum, newsum, empty = 0;
555 char *name; 555 char *name;
556 556
557 oldsum = TT.oldline + TT.oldlen; 557 oldsum = TT.oldline + TT.oldlen;
@@ -564,7 +564,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
564 if (!strcmp(name, "/dev/null") || !(reverse ? oldsum : newsum)) 564 if (!strcmp(name, "/dev/null") || !(reverse ? oldsum : newsum))
565 { 565 {
566 name = reverse ? newname : oldname; 566 name = reverse ? newname : oldname;
567 del++; 567 empty++;
568 } 568 }
569 569
570 // handle -p path truncation. 570 // handle -p path truncation.
@@ -576,10 +576,17 @@ int patch_main(int argc UNUSED_PARAM, char **argv)
576 } 576 }
577 } 577 }
578 578
579 if (del) { 579 if (empty) {
580 printf("removing %s\n", name); 580 // File is empty after the patches have been applied
581 xunlink(name);
582 state = 0; 581 state = 0;
582 if (option_mask32 & FLAG_RMEMPTY) {
583 // If flag -E or --remove-empty-files is set
584 printf("removing %s\n", name);
585 xunlink(name);
586 } else {
587 printf("patching file %s\n", name);
588 xclose(xopen(name, O_WRONLY | O_TRUNC));
589 }
583 // If we've got a file to open, do so. 590 // If we've got a file to open, do so.
584 } else if (!(option_mask32 & FLAG_PATHLEN) || i <= TT.prefix) { 591 } else if (!(option_mask32 & FLAG_PATHLEN) || i <= TT.prefix) {
585 // If the old file was null, we're creating a new one. 592 // If the old file was null, we're creating a new one.
diff --git a/include/libbb.h b/include/libbb.h
index 0ea7700f2..99bfe085c 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1532,47 +1532,31 @@ enum {
1532}; 1532};
1533void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags); 1533void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags);
1534 1534
1535typedef struct sha1_ctx_t { 1535typedef struct md5_ctx_t {
1536 uint32_t hash[8]; /* 5, +3 elements for sha256 */ 1536 uint8_t wbuffer[64]; /* always correctly aligned for uint64_t */
1537 uint64_t total64; /* must be directly after hash[] */ 1537 void (*process_block)(struct md5_ctx_t*) FAST_FUNC;
1538 uint8_t wbuffer[64]; /* NB: always correctly aligned for uint64_t */ 1538 uint64_t total64; /* must be directly before hash[] */
1539 void (*process_block)(struct sha1_ctx_t*) FAST_FUNC; 1539 uint32_t hash[8]; /* 4 elements for md5, 5 for sha1, 8 for sha256 */
1540} sha1_ctx_t; 1540} md5_ctx_t;
1541void sha1_begin(sha1_ctx_t *ctx) FAST_FUNC; 1541typedef struct md5_ctx_t sha1_ctx_t;
1542void sha1_hash(sha1_ctx_t *ctx, const void *data, size_t length) FAST_FUNC; 1542typedef struct md5_ctx_t sha256_ctx_t;
1543void sha1_end(sha1_ctx_t *ctx, void *resbuf) FAST_FUNC;
1544typedef struct sha1_ctx_t sha256_ctx_t;
1545void sha256_begin(sha256_ctx_t *ctx) FAST_FUNC;
1546#define sha256_hash sha1_hash
1547#define sha256_end sha1_end
1548typedef struct sha512_ctx_t { 1543typedef struct sha512_ctx_t {
1544 uint64_t total64[2]; /* must be directly before hash[] */
1549 uint64_t hash[8]; 1545 uint64_t hash[8];
1550 uint64_t total64[2]; /* must be directly after hash[] */ 1546 uint8_t wbuffer[128]; /* always correctly aligned for uint64_t */
1551 uint8_t wbuffer[128]; /* NB: always correctly aligned for uint64_t */
1552} sha512_ctx_t; 1547} sha512_ctx_t;
1553void sha512_begin(sha512_ctx_t *ctx) FAST_FUNC;
1554void sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC;
1555void sha512_end(sha512_ctx_t *ctx, void *resbuf) FAST_FUNC;
1556#if 1
1557typedef struct md5_ctx_t {
1558 uint32_t A;
1559 uint32_t B;
1560 uint32_t C;
1561 uint32_t D;
1562 uint64_t total64;
1563 char wbuffer[64]; /* NB: always correctly aligned for uint64_t */
1564} md5_ctx_t;
1565#else
1566/* libbb/md5prime.c uses a bit different one: */
1567typedef struct md5_ctx_t {
1568 uint32_t state[4]; /* state (ABCD) */
1569 uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
1570 unsigned char buffer[64]; /* input buffer */
1571} md5_ctx_t;
1572#endif
1573void md5_begin(md5_ctx_t *ctx) FAST_FUNC; 1548void md5_begin(md5_ctx_t *ctx) FAST_FUNC;
1574void md5_hash(md5_ctx_t *ctx, const void *data, size_t length) FAST_FUNC; 1549void md5_hash(md5_ctx_t *ctx, const void *data, size_t length) FAST_FUNC;
1575void md5_end(md5_ctx_t *ctx, void *resbuf) FAST_FUNC; 1550void md5_end(md5_ctx_t *ctx, void *resbuf) FAST_FUNC;
1551void sha1_begin(sha1_ctx_t *ctx) FAST_FUNC;
1552#define sha1_hash md5_hash
1553void sha1_end(sha1_ctx_t *ctx, void *resbuf) FAST_FUNC;
1554void sha256_begin(sha256_ctx_t *ctx) FAST_FUNC;
1555#define sha256_hash md5_hash
1556#define sha256_end sha1_end
1557void sha512_begin(sha512_ctx_t *ctx) FAST_FUNC;
1558void sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) FAST_FUNC;
1559void sha512_end(sha512_ctx_t *ctx, void *resbuf) FAST_FUNC;
1576 1560
1577 1561
1578uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC; 1562uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC;
diff --git a/include/usage.src.h b/include/usage.src.h
index 5d7767bb4..f5ddd7ba5 100644
--- a/include/usage.src.h
+++ b/include/usage.src.h
@@ -2788,7 +2788,7 @@ INSERT
2788 "Address: 127.0.0.1\n" 2788 "Address: 127.0.0.1\n"
2789 2789
2790#define ntpd_trivial_usage \ 2790#define ntpd_trivial_usage \
2791 "[-dnqwl] [-S PROG] [-p PEER]..." 2791 "[-dnqNw"IF_FEATURE_NTPD_SERVER("l")"] [-S PROG] [-p PEER]..."
2792#define ntpd_full_usage "\n\n" \ 2792#define ntpd_full_usage "\n\n" \
2793 "NTP client/server\n" \ 2793 "NTP client/server\n" \
2794 "\nOptions:" \ 2794 "\nOptions:" \
@@ -2797,7 +2797,9 @@ INSERT
2797 "\n -q Quit after clock is set" \ 2797 "\n -q Quit after clock is set" \
2798 "\n -N Run at high priority" \ 2798 "\n -N Run at high priority" \
2799 "\n -w Do not set time (only query peers), implies -n" \ 2799 "\n -w Do not set time (only query peers), implies -n" \
2800 IF_FEATURE_NTPD_SERVER( \
2800 "\n -l Run as server on port 123" \ 2801 "\n -l Run as server on port 123" \
2802 ) \
2801 "\n -S PROG Run PROG after stepping time, stratum change, and every 11 mins" \ 2803 "\n -S PROG Run PROG after stepping time, stratum change, and every 11 mins" \
2802 "\n -p PEER Obtain time from PEER (may be repeated)" \ 2804 "\n -p PEER Obtain time from PEER (may be repeated)" \
2803 2805
@@ -2855,17 +2857,19 @@ INSERT
2855 "[OPTIONS] [ORIGFILE [PATCHFILE]]" 2857 "[OPTIONS] [ORIGFILE [PATCHFILE]]"
2856#define patch_full_usage "\n\n" \ 2858#define patch_full_usage "\n\n" \
2857 IF_LONG_OPTS( \ 2859 IF_LONG_OPTS( \
2858 " -p,--strip N Strip N leading components from file names" \ 2860 " -p,--strip N Strip N leading components from file names" \
2859 "\n -i,--input DIFF Read DIFF instead of stdin" \ 2861 "\n -i,--input DIFF Read DIFF instead of stdin" \
2860 "\n -R,--reverse Reverse patch" \ 2862 "\n -R,--reverse Reverse patch" \
2861 "\n -N,--forward Ignore already applied patches" \ 2863 "\n -N,--forward Ignore already applied patches" \
2862 "\n --dry-run Don't actually change files" \ 2864 "\n --dry-run Don't actually change files" \
2865 "\n -E,--remove-empty-files Remove output files if they become empty" \
2863 ) \ 2866 ) \
2864 IF_NOT_LONG_OPTS( \ 2867 IF_NOT_LONG_OPTS( \
2865 " -p N Strip N leading components from file names" \ 2868 " -p N Strip N leading components from file names" \
2866 "\n -i DIFF Read DIFF instead of stdin" \ 2869 "\n -i DIFF Read DIFF instead of stdin" \
2867 "\n -R Reverse patch" \ 2870 "\n -R Reverse patch" \
2868 "\n -N Ignore already applied patches" \ 2871 "\n -N Ignore already applied patches" \
2872 "\n -E Remove output files if they become empty" \
2869 ) 2873 )
2870 2874
2871#define patch_example_usage \ 2875#define patch_example_usage \
@@ -4232,84 +4236,6 @@ INSERT
4232 "# tunctl\n" \ 4236 "# tunctl\n" \
4233 "# tunctl -d tun0\n" 4237 "# tunctl -d tun0\n"
4234 4238
4235#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
4236# define IF_UDHCP_VERBOSE(...) __VA_ARGS__
4237#else
4238# define IF_UDHCP_VERBOSE(...)
4239#endif
4240#define udhcpc_trivial_usage \
4241 "[-fbnq"IF_UDHCP_VERBOSE("v")"oCR] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]\n" \
4242 " [-H HOSTNAME] [-c CID] [-V VENDOR] [-O DHCP_OPT]..." IF_FEATURE_UDHCP_PORT(" [-P N]")
4243#define udhcpc_full_usage "\n" \
4244 IF_LONG_OPTS( \
4245 "\n -i,--interface IFACE Interface to use (default eth0)" \
4246 "\n -p,--pidfile FILE Create pidfile" \
4247 "\n -r,--request IP IP address to request" \
4248 "\n -s,--script PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")" \
4249 "\n -t,--retries N Send up to N discover packets" \
4250 "\n -T,--timeout N Pause between packets (default 3 seconds)" \
4251 "\n -A,--tryagain N Wait N seconds after failure (default 20)" \
4252 "\n -f,--foreground Run in foreground" \
4253 USE_FOR_MMU( \
4254 "\n -b,--background Background if lease is not obtained" \
4255 ) \
4256 "\n -S,--syslog Log to syslog too" \
4257 "\n -n,--now Exit if lease is not obtained" \
4258 "\n -q,--quit Exit after obtaining lease" \
4259 "\n -R,--release Release IP on exit" \
4260 IF_FEATURE_UDHCP_PORT( \
4261 "\n -P,--client-port N Use port N (default 68)" \
4262 ) \
4263 IF_FEATURE_UDHCPC_ARPING( \
4264 "\n -a,--arping Use arping to validate offered address" \
4265 ) \
4266 "\n -O,--request-option OPT Request DHCP option OPT (cumulative)" \
4267 "\n -o,--no-default-options Don't request any options (unless -O is given)" \
4268 "\n -x OPT:VAL Include option OPT in sent packets (cumulative)" \
4269 "\n -F,--fqdn NAME Ask server to update DNS mapping for NAME" \
4270 "\n -H,-h,--hostname NAME Send NAME as client hostname (default none)" \
4271 "\n -V,--vendorclass VENDOR Vendor identifier (default 'udhcp VERSION')" \
4272 "\n -c,--clientid CLIENTID Client identifier (default own MAC)" \
4273 "\n -C,--clientid-none Don't send client identifier" \
4274 IF_UDHCP_VERBOSE( \
4275 "\n -v Verbose" \
4276 ) \
4277 ) \
4278 IF_NOT_LONG_OPTS( \
4279 "\n -i IFACE Interface to use (default eth0)" \
4280 "\n -p FILE Create pidfile" \
4281 "\n -r IP IP address to request" \
4282 "\n -s PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")" \
4283 "\n -t N Send up to N discover packets" \
4284 "\n -T N Pause between packets (default 3 seconds)" \
4285 "\n -A N Wait N seconds (default 20) after failure" \
4286 "\n -x OPT:VAL Include option OPT in sent packets" \
4287 "\n -O OPT Request DHCP option OPT (cumulative)" \
4288 "\n -o Don't request any options (unless -O is given)" \
4289 "\n -f Run in foreground" \
4290 USE_FOR_MMU( \
4291 "\n -b Background if lease is not obtained" \
4292 ) \
4293 "\n -S Log to syslog too" \
4294 "\n -n Exit if lease is not obtained" \
4295 "\n -q Exit after obtaining lease" \
4296 "\n -R Release IP on exit" \
4297 IF_FEATURE_UDHCP_PORT( \
4298 "\n -P N Use port N (default 68)" \
4299 ) \
4300 IF_FEATURE_UDHCPC_ARPING( \
4301 "\n -a Use arping to validate offered address" \
4302 ) \
4303 "\n -F NAME Ask server to update DNS mapping for NAME" \
4304 "\n -H,-h NAME Send NAME as client hostname (default none)" \
4305 "\n -V VENDOR Vendor identifier (default 'udhcp VERSION')" \
4306 "\n -c CLIENTID Client identifier (default own MAC)" \
4307 "\n -C Don't send client identifier" \
4308 IF_UDHCP_VERBOSE( \
4309 "\n -v Verbose" \
4310 ) \
4311 ) \
4312
4313#define udhcpd_trivial_usage \ 4239#define udhcpd_trivial_usage \
4314 "[-fS]" IF_FEATURE_UDHCP_PORT(" [-P N]") " [CONFFILE]" \ 4240 "[-fS]" IF_FEATURE_UDHCP_PORT(" [-P N]") " [CONFFILE]" \
4315 4241
diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c
index 3e708ef7e..aeacddef8 100644
--- a/libbb/hash_md5_sha.c
+++ b/libbb/hash_md5_sha.c
@@ -1,31 +1,10 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * Based on shasum from http://www.netsw.org/crypto/hash/ 3 * Utility routines.
4 * Majorly hacked up to use Dr Brian Gladman's sha1 code
5 * 4 *
6 * Copyright (C) 2002 Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK. 5 * Copyright (C) 2010 Denys Vlasenko
7 * Copyright (C) 2003 Glenn L. McGrath
8 * Copyright (C) 2003 Erik Andersen
9 * 6 *
10 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
11 *
12 * ---------------------------------------------------------------------------
13 * Issue Date: 10/11/2002
14 *
15 * This is a byte oriented version of SHA1 that operates on arrays of bytes
16 * stored in memory. It runs at 22 cycles per byte on a Pentium P4 processor
17 *
18 * ---------------------------------------------------------------------------
19 *
20 * SHA256 and SHA512 parts are:
21 * Released into the Public Domain by Ulrich Drepper <drepper@redhat.com>.
22 * Shrank by Denys Vlasenko.
23 *
24 * ---------------------------------------------------------------------------
25 *
26 * The best way to test random blocksizes is to go to coreutils/md5_sha1_sum.c
27 * and replace "4096" with something like "2000 + time(NULL) % 2097",
28 * then rebuild and compare "shaNNNsum bigfile" results.
29 */ 8 */
30 9
31#include "libbb.h" 10#include "libbb.h"
@@ -53,332 +32,18 @@ static ALWAYS_INLINE uint64_t rotr64(uint64_t x, unsigned n)
53} 32}
54 33
55 34
56static void FAST_FUNC sha1_process_block64(sha1_ctx_t *ctx) 35/* Feed data through a temporary buffer.
57{ 36 * The internal buffer remembers previous data until it has 64
58 unsigned t; 37 * bytes worth to pass on.
59 uint32_t W[80], a, b, c, d, e;
60 const uint32_t *words = (uint32_t*) ctx->wbuffer;
61
62 for (t = 0; t < 16; ++t)
63 W[t] = SWAP_BE32(words[t]);
64 for (/*t = 16*/; t < 80; ++t) {
65 uint32_t T = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16];
66 W[t] = rotl32(T, 1);
67 }
68
69 a = ctx->hash[0];
70 b = ctx->hash[1];
71 c = ctx->hash[2];
72 d = ctx->hash[3];
73 e = ctx->hash[4];
74
75#undef ch
76#undef parity
77#undef maj
78#undef rnd
79#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
80#define parity(x,y,z) ((x) ^ (y) ^ (z))
81#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) | (y))))
82/* A normal version as set out in the FIPS. */
83#define rnd(f,k) \
84 do { \
85 uint32_t T = a; \
86 a = rotl32(a, 5) + f(b, c, d) + e + k + W[t]; \
87 e = d; \
88 d = c; \
89 c = rotl32(b, 30); \
90 b = T; \
91 } while (0)
92
93 for (t = 0; t < 20; ++t)
94 rnd(ch, 0x5a827999);
95
96 for (/*t = 20*/; t < 40; ++t)
97 rnd(parity, 0x6ed9eba1);
98
99 for (/*t = 40*/; t < 60; ++t)
100 rnd(maj, 0x8f1bbcdc);
101
102 for (/*t = 60*/; t < 80; ++t)
103 rnd(parity, 0xca62c1d6);
104#undef ch
105#undef parity
106#undef maj
107#undef rnd
108
109 ctx->hash[0] += a;
110 ctx->hash[1] += b;
111 ctx->hash[2] += c;
112 ctx->hash[3] += d;
113 ctx->hash[4] += e;
114}
115
116/* Constants for SHA512 from FIPS 180-2:4.2.3.
117 * SHA256 constants from FIPS 180-2:4.2.2
118 * are the most significant half of first 64 elements
119 * of the same array.
120 */ 38 */
121static const uint64_t sha_K[80] = { 39static void FAST_FUNC common64_hash(md5_ctx_t *ctx, const void *buffer, size_t len)
122 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
123 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
124 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
125 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
126 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
127 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
128 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
129 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
130 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
131 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
132 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
133 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
134 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
135 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
136 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
137 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
138 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
139 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
140 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
141 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
142 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
143 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
144 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
145 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
146 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
147 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
148 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
149 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
150 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
151 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
152 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
153 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
154 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, /* [64]+ are used for sha512 only */
155 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
156 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
157 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
158 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
159 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
160 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
161 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
162};
163
164#undef Ch
165#undef Maj
166#undef S0
167#undef S1
168#undef R0
169#undef R1
170
171static void FAST_FUNC sha256_process_block64(sha256_ctx_t *ctx)
172{
173 unsigned t;
174 uint32_t W[64], a, b, c, d, e, f, g, h;
175 const uint32_t *words = (uint32_t*) ctx->wbuffer;
176
177 /* Operators defined in FIPS 180-2:4.1.2. */
178#define Ch(x, y, z) ((x & y) ^ (~x & z))
179#define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
180#define S0(x) (rotr32(x, 2) ^ rotr32(x, 13) ^ rotr32(x, 22))
181#define S1(x) (rotr32(x, 6) ^ rotr32(x, 11) ^ rotr32(x, 25))
182#define R0(x) (rotr32(x, 7) ^ rotr32(x, 18) ^ (x >> 3))
183#define R1(x) (rotr32(x, 17) ^ rotr32(x, 19) ^ (x >> 10))
184
185 /* Compute the message schedule according to FIPS 180-2:6.2.2 step 2. */
186 for (t = 0; t < 16; ++t)
187 W[t] = SWAP_BE32(words[t]);
188 for (/*t = 16*/; t < 64; ++t)
189 W[t] = R1(W[t - 2]) + W[t - 7] + R0(W[t - 15]) + W[t - 16];
190
191 a = ctx->hash[0];
192 b = ctx->hash[1];
193 c = ctx->hash[2];
194 d = ctx->hash[3];
195 e = ctx->hash[4];
196 f = ctx->hash[5];
197 g = ctx->hash[6];
198 h = ctx->hash[7];
199
200 /* The actual computation according to FIPS 180-2:6.2.2 step 3. */
201 for (t = 0; t < 64; ++t) {
202 /* Need to fetch upper half of sha_K[t]
203 * (I hope compiler is clever enough to just fetch
204 * upper half)
205 */
206 uint32_t K_t = sha_K[t] >> 32;
207 uint32_t T1 = h + S1(e) + Ch(e, f, g) + K_t + W[t];
208 uint32_t T2 = S0(a) + Maj(a, b, c);
209 h = g;
210 g = f;
211 f = e;
212 e = d + T1;
213 d = c;
214 c = b;
215 b = a;
216 a = T1 + T2;
217 }
218#undef Ch
219#undef Maj
220#undef S0
221#undef S1
222#undef R0
223#undef R1
224 /* Add the starting values of the context according to FIPS 180-2:6.2.2
225 step 4. */
226 ctx->hash[0] += a;
227 ctx->hash[1] += b;
228 ctx->hash[2] += c;
229 ctx->hash[3] += d;
230 ctx->hash[4] += e;
231 ctx->hash[5] += f;
232 ctx->hash[6] += g;
233 ctx->hash[7] += h;
234}
235
236static void FAST_FUNC sha512_process_block128(sha512_ctx_t *ctx)
237{
238 unsigned t;
239 uint64_t W[80];
240 /* On i386, having assignments here (not later as sha256 does)
241 * produces 99 bytes smaller code with gcc 4.3.1
242 */
243 uint64_t a = ctx->hash[0];
244 uint64_t b = ctx->hash[1];
245 uint64_t c = ctx->hash[2];
246 uint64_t d = ctx->hash[3];
247 uint64_t e = ctx->hash[4];
248 uint64_t f = ctx->hash[5];
249 uint64_t g = ctx->hash[6];
250 uint64_t h = ctx->hash[7];
251 const uint64_t *words = (uint64_t*) ctx->wbuffer;
252
253 /* Operators defined in FIPS 180-2:4.1.2. */
254#define Ch(x, y, z) ((x & y) ^ (~x & z))
255#define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
256#define S0(x) (rotr64(x, 28) ^ rotr64(x, 34) ^ rotr64(x, 39))
257#define S1(x) (rotr64(x, 14) ^ rotr64(x, 18) ^ rotr64(x, 41))
258#define R0(x) (rotr64(x, 1) ^ rotr64(x, 8) ^ (x >> 7))
259#define R1(x) (rotr64(x, 19) ^ rotr64(x, 61) ^ (x >> 6))
260
261 /* Compute the message schedule according to FIPS 180-2:6.3.2 step 2. */
262 for (t = 0; t < 16; ++t)
263 W[t] = SWAP_BE64(words[t]);
264 for (/*t = 16*/; t < 80; ++t)
265 W[t] = R1(W[t - 2]) + W[t - 7] + R0(W[t - 15]) + W[t - 16];
266
267 /* The actual computation according to FIPS 180-2:6.3.2 step 3. */
268 for (t = 0; t < 80; ++t) {
269 uint64_t T1 = h + S1(e) + Ch(e, f, g) + sha_K[t] + W[t];
270 uint64_t T2 = S0(a) + Maj(a, b, c);
271 h = g;
272 g = f;
273 f = e;
274 e = d + T1;
275 d = c;
276 c = b;
277 b = a;
278 a = T1 + T2;
279 }
280#undef Ch
281#undef Maj
282#undef S0
283#undef S1
284#undef R0
285#undef R1
286 /* Add the starting values of the context according to FIPS 180-2:6.3.2
287 step 4. */
288 ctx->hash[0] += a;
289 ctx->hash[1] += b;
290 ctx->hash[2] += c;
291 ctx->hash[3] += d;
292 ctx->hash[4] += e;
293 ctx->hash[5] += f;
294 ctx->hash[6] += g;
295 ctx->hash[7] += h;
296}
297
298
299void FAST_FUNC sha1_begin(sha1_ctx_t *ctx)
300{
301 ctx->hash[0] = 0x67452301;
302 ctx->hash[1] = 0xefcdab89;
303 ctx->hash[2] = 0x98badcfe;
304 ctx->hash[3] = 0x10325476;
305 ctx->hash[4] = 0xc3d2e1f0;
306 ctx->total64 = 0;
307 ctx->process_block = sha1_process_block64;
308}
309
310static const uint32_t init256[] = {
311 0x6a09e667,
312 0xbb67ae85,
313 0x3c6ef372,
314 0xa54ff53a,
315 0x510e527f,
316 0x9b05688c,
317 0x1f83d9ab,
318 0x5be0cd19,
319 0,
320 0,
321};
322static const uint32_t init512_lo[] = {
323 0xf3bcc908,
324 0x84caa73b,
325 0xfe94f82b,
326 0x5f1d36f1,
327 0xade682d1,
328 0x2b3e6c1f,
329 0xfb41bd6b,
330 0x137e2179,
331 0,
332 0,
333};
334
335/* Initialize structure containing state of computation.
336 (FIPS 180-2:5.3.2) */
337void FAST_FUNC sha256_begin(sha256_ctx_t *ctx)
338{
339 memcpy(ctx->hash, init256, sizeof(init256));
340 /*ctx->total64 = 0; - done by extending init256 with two 32-bit zeros */
341 ctx->process_block = sha256_process_block64;
342}
343
344/* Initialize structure containing state of computation.
345 (FIPS 180-2:5.3.3) */
346void FAST_FUNC sha512_begin(sha512_ctx_t *ctx)
347{
348 int i;
349 /* Two extra iterations zero out ctx->total64[] */
350 for (i = 0; i < 8+2; i++)
351 ctx->hash[i] = ((uint64_t)(init256[i]) << 32) + init512_lo[i];
352 /*ctx->total64[0] = ctx->total64[1] = 0; - already done */
353}
354
355
356/* Used also for sha256 */
357void FAST_FUNC sha1_hash(sha1_ctx_t *ctx, const void *buffer, size_t len)
358{ 40{
359 unsigned bufpos = ctx->total64 & 63; 41 unsigned bufpos = ctx->total64 & 63;
360 unsigned remaining;
361 42
362 ctx->total64 += len; 43 ctx->total64 += len;
363#if 0
364 remaining = 64 - bufpos;
365
366 /* Hash whole blocks */
367 while (len >= remaining) {
368 memcpy(ctx->wbuffer + bufpos, buffer, remaining);
369 buffer = (const char *)buffer + remaining;
370 len -= remaining;
371 remaining = 64;
372 bufpos = 0;
373 ctx->process_block(ctx);
374 }
375 44
376 /* Save last, partial blosk */
377 memcpy(ctx->wbuffer + bufpos, buffer, len);
378#else
379 /* Tiny bit smaller code */
380 while (1) { 45 while (1) {
381 remaining = 64 - bufpos; 46 unsigned remaining = 64 - bufpos;
382 if (remaining > len) 47 if (remaining > len)
383 remaining = len; 48 remaining = len;
384 /* Copy data into aligned buffer */ 49 /* Copy data into aligned buffer */
@@ -394,62 +59,12 @@ void FAST_FUNC sha1_hash(sha1_ctx_t *ctx, const void *buffer, size_t len)
394 ctx->process_block(ctx); 59 ctx->process_block(ctx);
395 /*bufpos = 0; - already is */ 60 /*bufpos = 0; - already is */
396 } 61 }
397#endif
398} 62}
399 63
400void FAST_FUNC sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len) 64/* Process the remaining bytes in the buffer */
401{ 65static void FAST_FUNC common64_end(md5_ctx_t *ctx, int swap_needed)
402 unsigned bufpos = ctx->total64[0] & 127;
403 unsigned remaining;
404
405 /* First increment the byte count. FIPS 180-2 specifies the possible
406 length of the file up to 2^128 _bits_.
407 We compute the number of _bytes_ and convert to bits later. */
408 ctx->total64[0] += len;
409 if (ctx->total64[0] < len)
410 ctx->total64[1]++;
411#if 0
412 remaining = 128 - bufpos;
413
414 /* Hash whole blocks */
415 while (len >= remaining) {
416 memcpy(ctx->wbuffer + bufpos, buffer, remaining);
417 buffer = (const char *)buffer + remaining;
418 len -= remaining;
419 remaining = 128;
420 bufpos = 0;
421 sha512_process_block128(ctx);
422 }
423
424 /* Save last, partial blosk */
425 memcpy(ctx->wbuffer + bufpos, buffer, len);
426#else
427 while (1) {
428 remaining = 128 - bufpos;
429 if (remaining > len)
430 remaining = len;
431 /* Copy data into aligned buffer */
432 memcpy(ctx->wbuffer + bufpos, buffer, remaining);
433 len -= remaining;
434 buffer = (const char *)buffer + remaining;
435 bufpos += remaining;
436 /* clever way to do "if (bufpos != 128) break; ... ; bufpos = 0;" */
437 bufpos -= 128;
438 if (bufpos != 0)
439 break;
440 /* Buffer is filled up, process it */
441 sha512_process_block128(ctx);
442 /*bufpos = 0; - already is */
443 }
444#endif
445}
446
447
448/* Used also for sha256 */
449void FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf)
450{ 66{
451 unsigned bufpos = ctx->total64 & 63; 67 unsigned bufpos = ctx->total64 & 63;
452
453 /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */ 68 /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */
454 ctx->wbuffer[bufpos++] = 0x80; 69 ctx->wbuffer[bufpos++] = 0x80;
455 70
@@ -459,9 +74,10 @@ void FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf)
459 memset(ctx->wbuffer + bufpos, 0, remaining); 74 memset(ctx->wbuffer + bufpos, 0, remaining);
460 /* Do we have enough space for the length count? */ 75 /* Do we have enough space for the length count? */
461 if (remaining >= 8) { 76 if (remaining >= 8) {
462 /* Store the 64-bit counter of bits in the buffer in BE format */ 77 /* Store the 64-bit counter of bits in the buffer */
463 uint64_t t = ctx->total64 << 3; 78 uint64_t t = ctx->total64 << 3;
464 t = SWAP_BE64(t); 79 if (swap_needed)
80 t = bb_bswap_64(t);
465 /* wbuffer is suitably aligned for this */ 81 /* wbuffer is suitably aligned for this */
466 *(uint64_t *) (&ctx->wbuffer[64 - 8]) = t; 82 *(uint64_t *) (&ctx->wbuffer[64 - 8]) = t;
467 } 83 }
@@ -470,49 +86,6 @@ void FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf)
470 break; 86 break;
471 bufpos = 0; 87 bufpos = 0;
472 } 88 }
473
474 bufpos = (ctx->process_block == sha1_process_block64) ? 5 : 8;
475 /* This way we do not impose alignment constraints on resbuf: */
476 if (BB_LITTLE_ENDIAN) {
477 unsigned i;
478 for (i = 0; i < bufpos; ++i)
479 ctx->hash[i] = SWAP_BE32(ctx->hash[i]);
480 }
481 memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * bufpos);
482}
483
484void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf)
485{
486 unsigned bufpos = ctx->total64[0] & 127;
487
488 /* Pad the buffer to the next 128-byte boundary with 0x80,0,0,0... */
489 ctx->wbuffer[bufpos++] = 0x80;
490
491 while (1) {
492 unsigned remaining = 128 - bufpos;
493 memset(ctx->wbuffer + bufpos, 0, remaining);
494 if (remaining >= 16) {
495 /* Store the 128-bit counter of bits in the buffer in BE format */
496 uint64_t t;
497 t = ctx->total64[0] << 3;
498 t = SWAP_BE64(t);
499 *(uint64_t *) (&ctx->wbuffer[128 - 8]) = t;
500 t = (ctx->total64[1] << 3) | (ctx->total64[0] >> 61);
501 t = SWAP_BE64(t);
502 *(uint64_t *) (&ctx->wbuffer[128 - 16]) = t;
503 }
504 sha512_process_block128(ctx);
505 if (remaining >= 16)
506 break;
507 bufpos = 0;
508 }
509
510 if (BB_LITTLE_ENDIAN) {
511 unsigned i;
512 for (i = 0; i < ARRAY_SIZE(ctx->hash); ++i)
513 ctx->hash[i] = SWAP_BE64(ctx->hash[i]);
514 }
515 memcpy(resbuf, ctx->hash, sizeof(ctx->hash));
516} 89}
517 90
518 91
@@ -539,18 +112,6 @@ void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf)
539# define MD5_SIZE_VS_SPEED CONFIG_MD5_SIZE_VS_SPEED 112# define MD5_SIZE_VS_SPEED CONFIG_MD5_SIZE_VS_SPEED
540#endif 113#endif
541 114
542/* Initialize structure containing state of computation.
543 * (RFC 1321, 3.3: Step 3)
544 */
545void FAST_FUNC md5_begin(md5_ctx_t *ctx)
546{
547 ctx->A = 0x67452301;
548 ctx->B = 0xefcdab89;
549 ctx->C = 0x98badcfe;
550 ctx->D = 0x10325476;
551 ctx->total64 = 0;
552}
553
554/* These are the four functions used in the four steps of the MD5 algorithm 115/* These are the four functions used in the four steps of the MD5 algorithm
555 * and defined in the RFC 1321. The first function is a little bit optimized 116 * and defined in the RFC 1321. The first function is a little bit optimized
556 * (as found in Colin Plumbs public domain implementation). 117 * (as found in Colin Plumbs public domain implementation).
@@ -566,7 +127,7 @@ void FAST_FUNC md5_begin(md5_ctx_t *ctx)
566#define FI(b, c, d) (c ^ (b | ~d)) 127#define FI(b, c, d) (c ^ (b | ~d))
567 128
568/* Hash a single block, 64 bytes long and 4-byte aligned */ 129/* Hash a single block, 64 bytes long and 4-byte aligned */
569static void md5_process_block64(md5_ctx_t *ctx) 130static void FAST_FUNC md5_process_block64(md5_ctx_t *ctx)
570{ 131{
571#if MD5_SIZE_VS_SPEED > 0 132#if MD5_SIZE_VS_SPEED > 0
572 /* Before we start, one word to the strange constants. 133 /* Before we start, one word to the strange constants.
@@ -605,10 +166,10 @@ static void md5_process_block64(md5_ctx_t *ctx)
605 }; 166 };
606#endif 167#endif
607 uint32_t *words = (void*) ctx->wbuffer; 168 uint32_t *words = (void*) ctx->wbuffer;
608 uint32_t A = ctx->A; 169 uint32_t A = ctx->hash[0];
609 uint32_t B = ctx->B; 170 uint32_t B = ctx->hash[1];
610 uint32_t C = ctx->C; 171 uint32_t C = ctx->hash[2];
611 uint32_t D = ctx->D; 172 uint32_t D = ctx->hash[3];
612 173
613#if MD5_SIZE_VS_SPEED >= 2 /* 2 or 3 */ 174#if MD5_SIZE_VS_SPEED >= 2 /* 2 or 3 */
614 175
@@ -705,10 +266,10 @@ static void md5_process_block64(md5_ctx_t *ctx)
705 } 266 }
706# endif 267# endif
707 /* Add checksum to the starting values */ 268 /* Add checksum to the starting values */
708 ctx->A += A; 269 ctx->hash[0] += A;
709 ctx->B += B; 270 ctx->hash[1] += B;
710 ctx->C += C; 271 ctx->hash[2] += C;
711 ctx->D += D; 272 ctx->hash[3] += D;
712 273
713#else /* MD5_SIZE_VS_SPEED == 0 or 1 */ 274#else /* MD5_SIZE_VS_SPEED == 0 or 1 */
714 275
@@ -860,10 +421,10 @@ static void md5_process_block64(md5_ctx_t *ctx)
860# undef OP 421# undef OP
861# endif 422# endif
862 /* Add checksum to the starting values */ 423 /* Add checksum to the starting values */
863 ctx->A = A_save + A; 424 ctx->hash[0] = A_save + A;
864 ctx->B = B_save + B; 425 ctx->hash[1] = B_save + B;
865 ctx->C = C_save + C; 426 ctx->hash[2] = C_save + C;
866 ctx->D = D_save + D; 427 ctx->hash[3] = D_save + D;
867#endif 428#endif
868} 429}
869#undef FF 430#undef FF
@@ -871,37 +432,404 @@ static void md5_process_block64(md5_ctx_t *ctx)
871#undef FH 432#undef FH
872#undef FI 433#undef FI
873 434
874/* Feed data through a temporary buffer to call md5_hash_aligned_block() 435/* Initialize structure containing state of computation.
875 * with chunks of data that are 4-byte aligned and a multiple of 64 bytes. 436 * (RFC 1321, 3.3: Step 3)
876 * This function's internal buffer remembers previous data until it has 64 437 */
877 * bytes worth to pass on. Call md5_end() to flush this buffer. */ 438void FAST_FUNC md5_begin(md5_ctx_t *ctx)
439{
440 ctx->hash[0] = 0x67452301;
441 ctx->hash[1] = 0xefcdab89;
442 ctx->hash[2] = 0x98badcfe;
443 ctx->hash[3] = 0x10325476;
444 ctx->total64 = 0;
445 ctx->process_block = md5_process_block64;
446}
447
448/* Used also for sha1 and sha256 */
878void FAST_FUNC md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len) 449void FAST_FUNC md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len)
879{ 450{
880 unsigned bufpos = ctx->total64 & 63; 451 common64_hash(ctx, buffer, len);
452}
453
454/* Process the remaining bytes in the buffer and put result from CTX
455 * in first 16 bytes following RESBUF. The result is always in little
456 * endian byte order, so that a byte-wise output yields to the wanted
457 * ASCII representation of the message digest.
458 */
459void FAST_FUNC md5_end(md5_ctx_t *ctx, void *resbuf)
460{
461 /* MD5 stores total in LE, need to swap on BE arches: */
462 common64_end(ctx, /*swap_needed:*/ BB_BIG_ENDIAN);
463
464 /* The MD5 result is in little endian byte order */
465#if BB_BIG_ENDIAN
466 ctx->hash[0] = SWAP_LE32(ctx->hash[0]);
467 ctx->hash[1] = SWAP_LE32(ctx->hash[1]);
468 ctx->hash[2] = SWAP_LE32(ctx->hash[2]);
469 ctx->hash[3] = SWAP_LE32(ctx->hash[3]);
470#endif
471 memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * 4);
472}
473
474
475/*
476 * Based on shasum from http://www.netsw.org/crypto/hash/
477 * Majorly hacked up to use Dr Brian Gladman's sha1 code
478 *
479 * Copyright (C) 2002 Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
480 * Copyright (C) 2003 Glenn L. McGrath
481 * Copyright (C) 2003 Erik Andersen
482 *
483 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
484 *
485 * ---------------------------------------------------------------------------
486 * Issue Date: 10/11/2002
487 *
488 * This is a byte oriented version of SHA1 that operates on arrays of bytes
489 * stored in memory. It runs at 22 cycles per byte on a Pentium P4 processor
490 *
491 * ---------------------------------------------------------------------------
492 *
493 * SHA256 and SHA512 parts are:
494 * Released into the Public Domain by Ulrich Drepper <drepper@redhat.com>.
495 * Shrank by Denys Vlasenko.
496 *
497 * ---------------------------------------------------------------------------
498 *
499 * The best way to test random blocksizes is to go to coreutils/md5_sha1_sum.c
500 * and replace "4096" with something like "2000 + time(NULL) % 2097",
501 * then rebuild and compare "shaNNNsum bigfile" results.
502 */
503
504static void FAST_FUNC sha1_process_block64(sha1_ctx_t *ctx)
505{
506 unsigned t;
507 uint32_t W[80], a, b, c, d, e;
508 const uint32_t *words = (uint32_t*) ctx->wbuffer;
509
510 for (t = 0; t < 16; ++t)
511 W[t] = SWAP_BE32(words[t]);
512 for (/*t = 16*/; t < 80; ++t) {
513 uint32_t T = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16];
514 W[t] = rotl32(T, 1);
515 }
516
517 a = ctx->hash[0];
518 b = ctx->hash[1];
519 c = ctx->hash[2];
520 d = ctx->hash[3];
521 e = ctx->hash[4];
522
523#undef ch
524#undef parity
525#undef maj
526#undef rnd
527#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
528#define parity(x,y,z) ((x) ^ (y) ^ (z))
529#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) | (y))))
530/* A normal version as set out in the FIPS. */
531#define rnd(f,k) \
532 do { \
533 uint32_t T = a; \
534 a = rotl32(a, 5) + f(b, c, d) + e + k + W[t]; \
535 e = d; \
536 d = c; \
537 c = rotl32(b, 30); \
538 b = T; \
539 } while (0)
540
541 for (t = 0; t < 20; ++t)
542 rnd(ch, 0x5a827999);
543
544 for (/*t = 20*/; t < 40; ++t)
545 rnd(parity, 0x6ed9eba1);
546
547 for (/*t = 40*/; t < 60; ++t)
548 rnd(maj, 0x8f1bbcdc);
549
550 for (/*t = 60*/; t < 80; ++t)
551 rnd(parity, 0xca62c1d6);
552#undef ch
553#undef parity
554#undef maj
555#undef rnd
556
557 ctx->hash[0] += a;
558 ctx->hash[1] += b;
559 ctx->hash[2] += c;
560 ctx->hash[3] += d;
561 ctx->hash[4] += e;
562}
563
564/* Constants for SHA512 from FIPS 180-2:4.2.3.
565 * SHA256 constants from FIPS 180-2:4.2.2
566 * are the most significant half of first 64 elements
567 * of the same array.
568 */
569static const uint64_t sha_K[80] = {
570 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
571 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
572 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
573 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
574 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
575 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
576 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
577 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
578 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
579 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
580 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
581 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
582 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
583 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
584 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
585 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
586 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
587 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
588 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
589 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
590 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
591 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
592 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
593 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
594 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
595 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
596 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
597 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
598 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
599 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
600 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
601 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
602 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, /* [64]+ are used for sha512 only */
603 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
604 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
605 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
606 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
607 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
608 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
609 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
610};
611
612#undef Ch
613#undef Maj
614#undef S0
615#undef S1
616#undef R0
617#undef R1
618
619static void FAST_FUNC sha256_process_block64(sha256_ctx_t *ctx)
620{
621 unsigned t;
622 uint32_t W[64], a, b, c, d, e, f, g, h;
623 const uint32_t *words = (uint32_t*) ctx->wbuffer;
624
625 /* Operators defined in FIPS 180-2:4.1.2. */
626#define Ch(x, y, z) ((x & y) ^ (~x & z))
627#define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
628#define S0(x) (rotr32(x, 2) ^ rotr32(x, 13) ^ rotr32(x, 22))
629#define S1(x) (rotr32(x, 6) ^ rotr32(x, 11) ^ rotr32(x, 25))
630#define R0(x) (rotr32(x, 7) ^ rotr32(x, 18) ^ (x >> 3))
631#define R1(x) (rotr32(x, 17) ^ rotr32(x, 19) ^ (x >> 10))
632
633 /* Compute the message schedule according to FIPS 180-2:6.2.2 step 2. */
634 for (t = 0; t < 16; ++t)
635 W[t] = SWAP_BE32(words[t]);
636 for (/*t = 16*/; t < 64; ++t)
637 W[t] = R1(W[t - 2]) + W[t - 7] + R0(W[t - 15]) + W[t - 16];
638
639 a = ctx->hash[0];
640 b = ctx->hash[1];
641 c = ctx->hash[2];
642 d = ctx->hash[3];
643 e = ctx->hash[4];
644 f = ctx->hash[5];
645 g = ctx->hash[6];
646 h = ctx->hash[7];
647
648 /* The actual computation according to FIPS 180-2:6.2.2 step 3. */
649 for (t = 0; t < 64; ++t) {
650 /* Need to fetch upper half of sha_K[t]
651 * (I hope compiler is clever enough to just fetch
652 * upper half)
653 */
654 uint32_t K_t = sha_K[t] >> 32;
655 uint32_t T1 = h + S1(e) + Ch(e, f, g) + K_t + W[t];
656 uint32_t T2 = S0(a) + Maj(a, b, c);
657 h = g;
658 g = f;
659 f = e;
660 e = d + T1;
661 d = c;
662 c = b;
663 b = a;
664 a = T1 + T2;
665 }
666#undef Ch
667#undef Maj
668#undef S0
669#undef S1
670#undef R0
671#undef R1
672 /* Add the starting values of the context according to FIPS 180-2:6.2.2
673 step 4. */
674 ctx->hash[0] += a;
675 ctx->hash[1] += b;
676 ctx->hash[2] += c;
677 ctx->hash[3] += d;
678 ctx->hash[4] += e;
679 ctx->hash[5] += f;
680 ctx->hash[6] += g;
681 ctx->hash[7] += h;
682}
683
684static void FAST_FUNC sha512_process_block128(sha512_ctx_t *ctx)
685{
686 unsigned t;
687 uint64_t W[80];
688 /* On i386, having assignments here (not later as sha256 does)
689 * produces 99 bytes smaller code with gcc 4.3.1
690 */
691 uint64_t a = ctx->hash[0];
692 uint64_t b = ctx->hash[1];
693 uint64_t c = ctx->hash[2];
694 uint64_t d = ctx->hash[3];
695 uint64_t e = ctx->hash[4];
696 uint64_t f = ctx->hash[5];
697 uint64_t g = ctx->hash[6];
698 uint64_t h = ctx->hash[7];
699 const uint64_t *words = (uint64_t*) ctx->wbuffer;
700
701 /* Operators defined in FIPS 180-2:4.1.2. */
702#define Ch(x, y, z) ((x & y) ^ (~x & z))
703#define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
704#define S0(x) (rotr64(x, 28) ^ rotr64(x, 34) ^ rotr64(x, 39))
705#define S1(x) (rotr64(x, 14) ^ rotr64(x, 18) ^ rotr64(x, 41))
706#define R0(x) (rotr64(x, 1) ^ rotr64(x, 8) ^ (x >> 7))
707#define R1(x) (rotr64(x, 19) ^ rotr64(x, 61) ^ (x >> 6))
708
709 /* Compute the message schedule according to FIPS 180-2:6.3.2 step 2. */
710 for (t = 0; t < 16; ++t)
711 W[t] = SWAP_BE64(words[t]);
712 for (/*t = 16*/; t < 80; ++t)
713 W[t] = R1(W[t - 2]) + W[t - 7] + R0(W[t - 15]) + W[t - 16];
714
715 /* The actual computation according to FIPS 180-2:6.3.2 step 3. */
716 for (t = 0; t < 80; ++t) {
717 uint64_t T1 = h + S1(e) + Ch(e, f, g) + sha_K[t] + W[t];
718 uint64_t T2 = S0(a) + Maj(a, b, c);
719 h = g;
720 g = f;
721 f = e;
722 e = d + T1;
723 d = c;
724 c = b;
725 b = a;
726 a = T1 + T2;
727 }
728#undef Ch
729#undef Maj
730#undef S0
731#undef S1
732#undef R0
733#undef R1
734 /* Add the starting values of the context according to FIPS 180-2:6.3.2
735 step 4. */
736 ctx->hash[0] += a;
737 ctx->hash[1] += b;
738 ctx->hash[2] += c;
739 ctx->hash[3] += d;
740 ctx->hash[4] += e;
741 ctx->hash[5] += f;
742 ctx->hash[6] += g;
743 ctx->hash[7] += h;
744}
745
746
747void FAST_FUNC sha1_begin(sha1_ctx_t *ctx)
748{
749 ctx->hash[0] = 0x67452301;
750 ctx->hash[1] = 0xefcdab89;
751 ctx->hash[2] = 0x98badcfe;
752 ctx->hash[3] = 0x10325476;
753 ctx->hash[4] = 0xc3d2e1f0;
754 ctx->total64 = 0;
755 ctx->process_block = sha1_process_block64;
756}
757
758static const uint32_t init256[] = {
759 0,
760 0,
761 0x6a09e667,
762 0xbb67ae85,
763 0x3c6ef372,
764 0xa54ff53a,
765 0x510e527f,
766 0x9b05688c,
767 0x1f83d9ab,
768 0x5be0cd19,
769};
770static const uint32_t init512_lo[] = {
771 0,
772 0,
773 0xf3bcc908,
774 0x84caa73b,
775 0xfe94f82b,
776 0x5f1d36f1,
777 0xade682d1,
778 0x2b3e6c1f,
779 0xfb41bd6b,
780 0x137e2179,
781};
782
783/* Initialize structure containing state of computation.
784 (FIPS 180-2:5.3.2) */
785void FAST_FUNC sha256_begin(sha256_ctx_t *ctx)
786{
787 memcpy(&ctx->total64, init256, sizeof(init256));
788 /*ctx->total64 = 0; - done by prepending two 32-bit zeros to init256 */
789 ctx->process_block = sha256_process_block64;
790}
791
792/* Initialize structure containing state of computation.
793 (FIPS 180-2:5.3.3) */
794void FAST_FUNC sha512_begin(sha512_ctx_t *ctx)
795{
796 int i;
797 /* Two extra iterations zero out ctx->total64[2] */
798 uint64_t *tp = ctx->total64;
799 for (i = 0; i < 2+8; i++)
800 tp[i] = ((uint64_t)(init256[i]) << 32) + init512_lo[i];
801 /*ctx->total64[0] = ctx->total64[1] = 0; - already done */
802}
803
804void FAST_FUNC sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len)
805{
806 unsigned bufpos = ctx->total64[0] & 127;
881 unsigned remaining; 807 unsigned remaining;
882 808
883 /* RFC 1321 specifies the possible length of the file up to 2^64 bits. 809 /* First increment the byte count. FIPS 180-2 specifies the possible
884 * Here we only track the number of bytes. */ 810 length of the file up to 2^128 _bits_.
885 ctx->total64 += len; 811 We compute the number of _bytes_ and convert to bits later. */
812 ctx->total64[0] += len;
813 if (ctx->total64[0] < len)
814 ctx->total64[1]++;
886#if 0 815#if 0
887 remaining = 64 - bufpos; 816 remaining = 128 - bufpos;
888 817
889 /* Hash whole blocks */ 818 /* Hash whole blocks */
890 while (len >= remaining) { 819 while (len >= remaining) {
891 memcpy(ctx->wbuffer + bufpos, buffer, remaining); 820 memcpy(ctx->wbuffer + bufpos, buffer, remaining);
892 buffer = (const char *)buffer + remaining; 821 buffer = (const char *)buffer + remaining;
893 len -= remaining; 822 len -= remaining;
894 remaining = 64; 823 remaining = 128;
895 bufpos = 0; 824 bufpos = 0;
896 md5_process_block64(ctx); 825 sha512_process_block128(ctx);
897 } 826 }
898 827
899 /* Save last, partial blosk */ 828 /* Save last, partial blosk */
900 memcpy(ctx->wbuffer + bufpos, buffer, len); 829 memcpy(ctx->wbuffer + bufpos, buffer, len);
901#else 830#else
902 /* Tiny bit smaller code */
903 while (1) { 831 while (1) {
904 remaining = 64 - bufpos; 832 remaining = 128 - bufpos;
905 if (remaining > len) 833 if (remaining > len)
906 remaining = len; 834 remaining = len;
907 /* Copy data into aligned buffer */ 835 /* Copy data into aligned buffer */
@@ -909,54 +837,65 @@ void FAST_FUNC md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len)
909 len -= remaining; 837 len -= remaining;
910 buffer = (const char *)buffer + remaining; 838 buffer = (const char *)buffer + remaining;
911 bufpos += remaining; 839 bufpos += remaining;
912 /* clever way to do "if (bufpos != 64) break; ... ; bufpos = 0;" */ 840 /* clever way to do "if (bufpos != 128) break; ... ; bufpos = 0;" */
913 bufpos -= 64; 841 bufpos -= 128;
914 if (bufpos != 0) 842 if (bufpos != 0)
915 break; 843 break;
916 /* Buffer is filled up, process it */ 844 /* Buffer is filled up, process it */
917 md5_process_block64(ctx); 845 sha512_process_block128(ctx);
918 /*bufpos = 0; - already is */ 846 /*bufpos = 0; - already is */
919 } 847 }
920#endif 848#endif
921} 849}
922 850
923/* Process the remaining bytes in the buffer and put result from CTX 851/* Used also for sha256 */
924 * in first 16 bytes following RESBUF. The result is always in little 852void FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf)
925 * endian byte order, so that a byte-wise output yields to the wanted
926 * ASCII representation of the message digest.
927 */
928void FAST_FUNC md5_end(md5_ctx_t *ctx, void *resbuf)
929{ 853{
930 unsigned bufpos = ctx->total64 & 63; 854 unsigned hash_size;
931 /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */ 855
856 /* SHA stores total in BE, need to swap on LE arches: */
857 common64_end(ctx, /*swap_needed:*/ BB_LITTLE_ENDIAN);
858
859 hash_size = (ctx->process_block == sha1_process_block64) ? 5 : 8;
860 /* This way we do not impose alignment constraints on resbuf: */
861 if (BB_LITTLE_ENDIAN) {
862 unsigned i;
863 for (i = 0; i < hash_size; ++i)
864 ctx->hash[i] = SWAP_BE32(ctx->hash[i]);
865 }
866 memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * hash_size);
867}
868
869void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf)
870{
871 unsigned bufpos = ctx->total64[0] & 127;
872
873 /* Pad the buffer to the next 128-byte boundary with 0x80,0,0,0... */
932 ctx->wbuffer[bufpos++] = 0x80; 874 ctx->wbuffer[bufpos++] = 0x80;
933 875
934 /* This loop iterates either once or twice, no more, no less */
935 while (1) { 876 while (1) {
936 unsigned remaining = 64 - bufpos; 877 unsigned remaining = 128 - bufpos;
937 memset(ctx->wbuffer + bufpos, 0, remaining); 878 memset(ctx->wbuffer + bufpos, 0, remaining);
938 /* Do we have enough space for the length count? */ 879 if (remaining >= 16) {
939 if (remaining >= 8) { 880 /* Store the 128-bit counter of bits in the buffer in BE format */
940 /* Store the 64-bit counter of bits in the buffer in LE format */ 881 uint64_t t;
941 uint64_t t = ctx->total64 << 3; 882 t = ctx->total64[0] << 3;
942 t = SWAP_LE64(t); 883 t = SWAP_BE64(t);
943 /* wbuffer is suitably aligned for this */ 884 *(uint64_t *) (&ctx->wbuffer[128 - 8]) = t;
944 *(uint64_t *) (&ctx->wbuffer[64 - 8]) = t; 885 t = (ctx->total64[1] << 3) | (ctx->total64[0] >> 61);
886 t = SWAP_BE64(t);
887 *(uint64_t *) (&ctx->wbuffer[128 - 16]) = t;
945 } 888 }
946 md5_process_block64(ctx); 889 sha512_process_block128(ctx);
947 if (remaining >= 8) 890 if (remaining >= 16)
948 break; 891 break;
949 bufpos = 0; 892 bufpos = 0;
950 } 893 }
951 894
952 /* The MD5 result is in little endian byte order. 895 if (BB_LITTLE_ENDIAN) {
953 * We (ab)use the fact that A-D are consecutive in memory. 896 unsigned i;
954 */ 897 for (i = 0; i < ARRAY_SIZE(ctx->hash); ++i)
955#if BB_BIG_ENDIAN 898 ctx->hash[i] = SWAP_BE64(ctx->hash[i]);
956 ctx->A = SWAP_LE32(ctx->A); 899 }
957 ctx->B = SWAP_LE32(ctx->B); 900 memcpy(resbuf, ctx->hash, sizeof(ctx->hash));
958 ctx->C = SWAP_LE32(ctx->C);
959 ctx->D = SWAP_LE32(ctx->D);
960#endif
961 memcpy(resbuf, &ctx->A, sizeof(ctx->A) * 4);
962} 901}
diff --git a/libbb/safe_strncpy.c b/libbb/safe_strncpy.c
index 8eb6a014f..5eb0db0bd 100644
--- a/libbb/safe_strncpy.c
+++ b/libbb/safe_strncpy.c
@@ -20,8 +20,13 @@ char* FAST_FUNC safe_strncpy(char *dst, const char *src, size_t size)
20/* Like strcpy but can copy overlapping strings. */ 20/* Like strcpy but can copy overlapping strings. */
21void FAST_FUNC overlapping_strcpy(char *dst, const char *src) 21void FAST_FUNC overlapping_strcpy(char *dst, const char *src)
22{ 22{
23 while ((*dst = *src) != '\0') { 23 /* Cheap optimization for dst == src case -
24 dst++; 24 * better to have it here than in many callers.
25 src++; 25 */
26 if (dst != src) {
27 while ((*dst = *src) != '\0') {
28 dst++;
29 src++;
30 }
26 } 31 }
27} 32}
diff --git a/loginutils/add-remove-shell.c b/loginutils/add-remove-shell.c
new file mode 100644
index 000000000..757e50503
--- /dev/null
+++ b/loginutils/add-remove-shell.c
@@ -0,0 +1,135 @@
1/*
2 * add-shell and remove-shell implementation for busybox
3 *
4 * Copyright (C) 2010 Nokia Corporation. All rights reserved.
5 * Written by Alexander Shishkin <virtuoso@slind.org>
6 *
7 * Licensed under GPLv2 or later, see the LICENSE file in this source tree
8 * for details.
9 */
10
11//applet:IF_ADD_SHELL( APPLET_ODDNAME(add-shell , add_remove_shell, _BB_DIR_USR_BIN, _BB_SUID_DROP, add_shell ))
12//applet:IF_REMOVE_SHELL(APPLET_ODDNAME(remove-shell, add_remove_shell, _BB_DIR_USR_BIN, _BB_SUID_DROP, remove_shell))
13
14//kbuild:lib-$(CONFIG_ADD_SHELL) += add-remove-shell.o
15//kbuild:lib-$(CONFIG_REMOVE_SHELL) += add-remove-shell.o
16
17//config:config ADD_SHELL
18//config: bool "add-shell"
19//config: default y if DESKTOP
20//config: help
21//config: Add shells to /etc/shells.
22//config:
23//config:config REMOVE_SHELL
24//config: bool "remove-shell"
25//config: default y if DESKTOP
26//config: help
27//config: Remove shells from /etc/shells.
28
29//usage:#define add_shell_trivial_usage
30//usage: "SHELL..."
31//usage:#define add_shell_full_usage "\n\n"
32//usage: "Add SHELLs to /etc/shells"
33
34//usage:#define remove_shell_trivial_usage
35//usage: "SHELL..."
36//usage:#define remove_shell_full_usage "\n\n"
37//usage: "Remove SHELLs from /etc/shells"
38
39#include "libbb.h"
40
41#define SHELLS_FILE "/etc/shells"
42
43#define REMOVE_SHELL (ENABLE_REMOVE_SHELL && (!ENABLE_ADD_SHELL || applet_name[0] == 'r'))
44#define ADD_SHELL (ENABLE_ADD_SHELL && (!ENABLE_REMOVE_SHELL || applet_name[0] == 'a'))
45
46/* NB: we use the _address_, not the value, of this string
47 * as a "special value of pointer" in the code.
48 */
49static const char dont_add[] ALIGN1 = "\n";
50
51int add_remove_shell_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
52int add_remove_shell_main(int argc UNUSED_PARAM, char **argv)
53{
54 FILE *orig_fp;
55 char *orig_fn;
56 char *new_fn;
57
58 argv++;
59
60 orig_fn = xmalloc_follow_symlinks(SHELLS_FILE);
61 if (!orig_fn)
62 return EXIT_FAILURE;
63 orig_fp = fopen_for_read(orig_fn);
64
65 new_fn = xasprintf("%s.tmp", orig_fn);
66 /*
67 * O_TRUNC or O_EXCL? At the first glance, O_EXCL looks better,
68 * since it prevents races. But: (1) it requires a retry loop,
69 * (2) if /etc/shells.tmp is *stale*, then retry loop
70 * with O_EXCL will never succeed - it should have a timeout,
71 * after which it should revert to O_TRUNC.
72 * For now, I settle for O_TRUNC instead.
73 */
74 xmove_fd(xopen(new_fn, O_WRONLY | O_CREAT | O_TRUNC), STDOUT_FILENO);
75
76 /* TODO:
77 struct stat sb;
78 xfstat(fileno(orig_fp), &sb);
79 xfchown(STDOUT_FILENO, sb.st_uid, sb.st_gid);
80 xfchmod(STDOUT_FILENO, sb.st_mode);
81 */
82
83 if (orig_fp) {
84 /* Copy old file, possibly skipping removed shell names */
85 char *line;
86 while ((line = xmalloc_fgetline(orig_fp)) != NULL) {
87 char **cpp = argv;
88 while (*cpp) {
89 if (strcmp(*cpp, line) == 0) {
90 /* Old file has this shell name */
91 if (REMOVE_SHELL) {
92 /* we are remove-shell */
93 /* delete this name by not copying it */
94 goto next_line;
95 }
96 /* we are add-shell */
97 /* mark this name as "do not add" */
98 *cpp = (char*)dont_add;
99 }
100 cpp++;
101 }
102 /* copy shell name from old to new file */
103 printf("%s\n", line);
104 next_line:
105 free(line);
106 }
107 if (ENABLE_FEATURE_CLEAN_UP)
108 fclose(orig_fp);
109 }
110
111 if (ADD_SHELL) {
112 char **cpp = argv;
113 while (*cpp) {
114 if (*cpp != dont_add)
115 printf("%s\n", *cpp);
116 cpp++;
117 }
118 }
119
120 /* Ensure we wrote out everything */
121 if (fclose(stdout) != 0) {
122 xunlink(new_fn);
123 bb_perror_msg_and_die("%s: write error", new_fn);
124 }
125
126 /* Small hole: if rename fails, /etc/shells.tmp is not removed */
127 xrename(new_fn, orig_fn);
128
129 if (ENABLE_FEATURE_CLEAN_UP) {
130 free(orig_fn);
131 free(new_fn);
132 }
133
134 return EXIT_SUCCESS;
135}
diff --git a/miscutils/crond.c b/miscutils/crond.c
index fddddcd8c..7f2d54c9f 100644
--- a/miscutils/crond.c
+++ b/miscutils/crond.c
@@ -123,7 +123,7 @@ static void crondlog(const char *ctl, ...)
123 /* Syslog mode: all to syslog (logmode = LOGMODE_SYSLOG), */ 123 /* Syslog mode: all to syslog (logmode = LOGMODE_SYSLOG), */
124 if (!DebugOpt && G.log_filename) { 124 if (!DebugOpt && G.log_filename) {
125 /* Otherwise (log to file): we reopen log file at every write: */ 125 /* Otherwise (log to file): we reopen log file at every write: */
126 int logfd = open3_or_warn(G.log_filename, O_WRONLY | O_CREAT | O_APPEND, 0666); 126 int logfd = open_or_warn(G.log_filename, O_WRONLY | O_CREAT | O_APPEND);
127 if (logfd >= 0) 127 if (logfd >= 0)
128 xmove_fd(logfd, STDERR_FILENO); 128 xmove_fd(logfd, STDERR_FILENO);
129 } 129 }
diff --git a/miscutils/nandwrite.c b/miscutils/nandwrite.c
index 6c85ea346..de30a0c1f 100644
--- a/miscutils/nandwrite.c
+++ b/miscutils/nandwrite.c
@@ -60,7 +60,6 @@
60#define OPT_f (1 << 3) 60#define OPT_f (1 << 3)
61#define OPT_l (1 << 4) 61#define OPT_l (1 << 4)
62 62
63#define NAND_MAX_OOBSIZE 256
64/* helper for writing out 0xff for bad blocks pad */ 63/* helper for writing out 0xff for bad blocks pad */
65static void dump_bad(struct mtd_info_user *meminfo, unsigned len, int oob) 64static void dump_bad(struct mtd_info_user *meminfo, unsigned len, int oob)
66{ 65{
@@ -103,7 +102,7 @@ int nandwrite_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
103int nandwrite_main(int argc UNUSED_PARAM, char **argv) 102int nandwrite_main(int argc UNUSED_PARAM, char **argv)
104{ 103{
105 /* Buffer for OOB data */ 104 /* Buffer for OOB data */
106 unsigned char oobbuf[NAND_MAX_OOBSIZE]; 105 unsigned char *oobbuf;
107 unsigned opts; 106 unsigned opts;
108 int fd; 107 int fd;
109 ssize_t cnt; 108 ssize_t cnt;
@@ -135,10 +134,6 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv)
135 fd = xopen(argv[0], O_RDWR); 134 fd = xopen(argv[0], O_RDWR);
136 xioctl(fd, MEMGETINFO, &meminfo); 135 xioctl(fd, MEMGETINFO, &meminfo);
137 136
138 oob.start = 0;
139 oob.length = meminfo.oobsize;
140 oob.ptr = oobbuf;
141
142 mtdoffset = xstrtou(opt_s, 0); 137 mtdoffset = xstrtou(opt_s, 0);
143 if (IS_NANDDUMP && (opts & OPT_l)) { 138 if (IS_NANDDUMP && (opts & OPT_l)) {
144 unsigned length = xstrtou(opt_l, 0); 139 unsigned length = xstrtou(opt_l, 0);
@@ -153,6 +148,11 @@ int nandwrite_main(int argc UNUSED_PARAM, char **argv)
153 bb_error_msg_and_die("start address is not page aligned"); 148 bb_error_msg_and_die("start address is not page aligned");
154 149
155 filebuf = xmalloc(meminfo_writesize); 150 filebuf = xmalloc(meminfo_writesize);
151 oobbuf = xmalloc(meminfo.oobsize);
152
153 oob.start = 0;
154 oob.length = meminfo.oobsize;
155 oob.ptr = oobbuf;
156 156
157 blockstart = mtdoffset & ~(meminfo.erasesize - 1); 157 blockstart = mtdoffset & ~(meminfo.erasesize - 1);
158 if (blockstart != mtdoffset) { 158 if (blockstart != mtdoffset) {
diff --git a/networking/nbd-client.c b/networking/nbd-client.c
index 5ac190c32..8b856eda7 100644
--- a/networking/nbd-client.c
+++ b/networking/nbd-client.c
@@ -46,7 +46,9 @@ int nbdclient_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
46int nbdclient_main(int argc, char **argv) 46int nbdclient_main(int argc, char **argv)
47{ 47{
48 unsigned long timeout = 0; 48 unsigned long timeout = 0;
49#if BB_MMU
49 int nofork = 0; 50 int nofork = 0;
51#endif
50 char *host, *port, *device; 52 char *host, *port, *device;
51 struct nbd_header_t { 53 struct nbd_header_t {
52 uint64_t magic1; // "NBDMAGIC" 54 uint64_t magic1; // "NBDMAGIC"
diff --git a/networking/ntpd.c b/networking/ntpd.c
index ca4afa045..b7bd239b5 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -49,7 +49,7 @@
49/* High-level description of the algorithm: 49/* High-level description of the algorithm:
50 * 50 *
51 * We start running with very small poll_exp, BURSTPOLL, 51 * We start running with very small poll_exp, BURSTPOLL,
52 * in order to quickly accumulate INITIAL_SAMLPES datapoints 52 * in order to quickly accumulate INITIAL_SAMPLES datapoints
53 * for each peer. Then, time is stepped if the offset is larger 53 * for each peer. Then, time is stepped if the offset is larger
54 * than STEP_THRESHOLD, otherwise it isn't; anyway, we enlarge 54 * than STEP_THRESHOLD, otherwise it isn't; anyway, we enlarge
55 * poll_exp to MINPOLL and enter frequency measurement step: 55 * poll_exp to MINPOLL and enter frequency measurement step:
@@ -77,7 +77,7 @@
77 77
78#define RETRY_INTERVAL 5 /* on error, retry in N secs */ 78#define RETRY_INTERVAL 5 /* on error, retry in N secs */
79#define RESPONSE_INTERVAL 15 /* wait for reply up to N secs */ 79#define RESPONSE_INTERVAL 15 /* wait for reply up to N secs */
80#define INITIAL_SAMLPES 4 /* how many samples do we want for init */ 80#define INITIAL_SAMPLES 4 /* how many samples do we want for init */
81 81
82/* Clock discipline parameters and constants */ 82/* Clock discipline parameters and constants */
83 83
@@ -1972,14 +1972,14 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
1972 idx2peer = xzalloc(sizeof(idx2peer[0]) * cnt); 1972 idx2peer = xzalloc(sizeof(idx2peer[0]) * cnt);
1973 pfd = xzalloc(sizeof(pfd[0]) * cnt); 1973 pfd = xzalloc(sizeof(pfd[0]) * cnt);
1974 1974
1975 /* Countdown: we never sync before we sent INITIAL_SAMLPES+1 1975 /* Countdown: we never sync before we sent INITIAL_SAMPLES+1
1976 * packets to each peer. 1976 * packets to each peer.
1977 * NB: if some peer is not responding, we may end up sending 1977 * NB: if some peer is not responding, we may end up sending
1978 * fewer packets to it and more to other peers. 1978 * fewer packets to it and more to other peers.
1979 * NB2: sync usually happens using INITIAL_SAMLPES packets, 1979 * NB2: sync usually happens using INITIAL_SAMPLES packets,
1980 * since last reply does not come back instantaneously. 1980 * since last reply does not come back instantaneously.
1981 */ 1981 */
1982 cnt = G.peer_cnt * (INITIAL_SAMLPES + 1); 1982 cnt = G.peer_cnt * (INITIAL_SAMPLES + 1);
1983 1983
1984 while (!bb_got_signal) { 1984 while (!bb_got_signal) {
1985 llist_t *item; 1985 llist_t *item;
diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c
index b6b274d91..311f79e7e 100644
--- a/networking/udhcp/common.c
+++ b/networking/udhcp/common.c
@@ -68,9 +68,10 @@ const struct dhcp_optflag dhcp_optflags[] = {
68 { OPTION_IP , 0x32 }, /* DHCP_REQUESTED_IP */ 68 { OPTION_IP , 0x32 }, /* DHCP_REQUESTED_IP */
69 { OPTION_U8 , 0x35 }, /* DHCP_MESSAGE_TYPE */ 69 { OPTION_U8 , 0x35 }, /* DHCP_MESSAGE_TYPE */
70 { OPTION_U16 , 0x39 }, /* DHCP_MAX_SIZE */ 70 { OPTION_U16 , 0x39 }, /* DHCP_MAX_SIZE */
71 { OPTION_STRING , 0x3c }, /* DHCP_VENDOR */ 71//looks like these opts will work just fine even without these defs:
72//FIXME: handling of this option is not exactly correct: 72// { OPTION_STRING , 0x3c }, /* DHCP_VENDOR */
73 { OPTION_STRING , 0x3d }, /* DHCP_CLIENT_ID */ 73// /* not really a string: */
74// { OPTION_STRING , 0x3d }, /* DHCP_CLIENT_ID */
74 { 0, 0 } /* zeroed terminating entry */ 75 { 0, 0 } /* zeroed terminating entry */
75}; 76};
76 77
diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h
index 9020b9c96..f8f18ff01 100644
--- a/networking/udhcp/common.h
+++ b/networking/udhcp/common.h
@@ -63,14 +63,14 @@ struct udp_dhcp_packet {
63} PACKED; 63} PACKED;
64 64
65enum { 65enum {
66 IP_UPD_DHCP_SIZE = sizeof(struct ip_udp_dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS, 66 IP_UDP_DHCP_SIZE = sizeof(struct ip_udp_dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS,
67 UPD_DHCP_SIZE = sizeof(struct udp_dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS, 67 UDP_DHCP_SIZE = sizeof(struct udp_dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS,
68 DHCP_SIZE = sizeof(struct dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS, 68 DHCP_SIZE = sizeof(struct dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS,
69}; 69};
70 70
71/* Let's see whether compiler understood us right */ 71/* Let's see whether compiler understood us right */
72struct BUG_bad_sizeof_struct_ip_udp_dhcp_packet { 72struct BUG_bad_sizeof_struct_ip_udp_dhcp_packet {
73 char c[IP_UPD_DHCP_SIZE == 576 ? 1 : -1]; 73 char c[IP_UDP_DHCP_SIZE == 576 ? 1 : -1];
74}; 74};
75 75
76 76
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index 27d6ad1a8..78aabedf2 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -346,31 +346,28 @@ static ALWAYS_INLINE uint32_t random_xid(void)
346/* Initialize the packet with the proper defaults */ 346/* Initialize the packet with the proper defaults */
347static void init_packet(struct dhcp_packet *packet, char type) 347static void init_packet(struct dhcp_packet *packet, char type)
348{ 348{
349 /* Fill in: op, htype, hlen, cookie fields; message type option: */
349 udhcp_init_header(packet, type); 350 udhcp_init_header(packet, type);
351
352 packet->xid = random_xid();
353
350 memcpy(packet->chaddr, client_config.client_mac, 6); 354 memcpy(packet->chaddr, client_config.client_mac, 6);
351 if (client_config.clientid) 355 if (client_config.clientid)
352 udhcp_add_binary_option(packet, client_config.clientid); 356 udhcp_add_binary_option(packet, client_config.clientid);
353 if (client_config.hostname)
354 udhcp_add_binary_option(packet, client_config.hostname);
355 if (client_config.fqdn)
356 udhcp_add_binary_option(packet, client_config.fqdn);
357 if (type != DHCPDECLINE
358 && type != DHCPRELEASE
359 && client_config.vendorclass
360 ) {
361 udhcp_add_binary_option(packet, client_config.vendorclass);
362 }
363} 357}
364 358
365static void add_client_options(struct dhcp_packet *packet) 359static void add_client_options(struct dhcp_packet *packet)
366{ 360{
361 uint8_t c;
362 int i, end, len;
363
364 udhcp_add_simple_option(packet, DHCP_MAX_SIZE, htons(IP_UDP_DHCP_SIZE));
365
367 /* Add a "param req" option with the list of options we'd like to have 366 /* Add a "param req" option with the list of options we'd like to have
368 * from stubborn DHCP servers. Pull the data from the struct in common.c. 367 * from stubborn DHCP servers. Pull the data from the struct in common.c.
369 * No bounds checking because it goes towards the head of the packet. */ 368 * No bounds checking because it goes towards the head of the packet. */
370 uint8_t c; 369 end = udhcp_end_option(packet->options);
371 int end = udhcp_end_option(packet->options); 370 len = 0;
372 int i, len = 0;
373
374 for (i = 0; (c = dhcp_optflags[i].code) != 0; i++) { 371 for (i = 0; (c = dhcp_optflags[i].code) != 0; i++) {
375 if (( (dhcp_optflags[i].flags & OPTION_REQ) 372 if (( (dhcp_optflags[i].flags & OPTION_REQ)
376 && !client_config.no_default_options 373 && !client_config.no_default_options
@@ -387,6 +384,13 @@ static void add_client_options(struct dhcp_packet *packet)
387 packet->options[end + OPT_DATA + len] = DHCP_END; 384 packet->options[end + OPT_DATA + len] = DHCP_END;
388 } 385 }
389 386
387 if (client_config.vendorclass)
388 udhcp_add_binary_option(packet, client_config.vendorclass);
389 if (client_config.hostname)
390 udhcp_add_binary_option(packet, client_config.hostname);
391 if (client_config.fqdn)
392 udhcp_add_binary_option(packet, client_config.fqdn);
393
390 /* Add -x options if any */ 394 /* Add -x options if any */
391 { 395 {
392 struct option_set *curr = client_config.options; 396 struct option_set *curr = client_config.options;
@@ -428,17 +432,25 @@ static int raw_bcast_from_client_config_ifindex(struct dhcp_packet *packet)
428} 432}
429 433
430/* Broadcast a DHCP discover packet to the network, with an optionally requested IP */ 434/* Broadcast a DHCP discover packet to the network, with an optionally requested IP */
431static int send_discover(uint32_t xid, uint32_t requested) 435/* NOINLINE: limit stack usage in caller */
436static NOINLINE int send_discover(uint32_t xid, uint32_t requested)
432{ 437{
433 struct dhcp_packet packet; 438 struct dhcp_packet packet;
434 439
440 /* Fill in: op, htype, hlen, cookie, chaddr fields,
441 * random xid field (we override it below),
442 * client-id option (unless -C), message type option:
443 */
435 init_packet(&packet, DHCPDISCOVER); 444 init_packet(&packet, DHCPDISCOVER);
445
436 packet.xid = xid; 446 packet.xid = xid;
437 if (requested) 447 if (requested)
438 udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); 448 udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested);
439 /* Explicitly saying that we want RFC-compliant packets helps 449
440 * some buggy DHCP servers to NOT send bigger packets */ 450 /* Add options: maxsize,
441 udhcp_add_simple_option(&packet, DHCP_MAX_SIZE, htons(576)); 451 * optionally: hostname, fqdn, vendorclass,
452 * "param req" option according to -O, options specified with -x
453 */
442 add_client_options(&packet); 454 add_client_options(&packet);
443 455
444 bb_info_msg("Sending discover..."); 456 bb_info_msg("Sending discover...");
@@ -449,15 +461,39 @@ static int send_discover(uint32_t xid, uint32_t requested)
449/* RFC 2131 3.1 paragraph 3: 461/* RFC 2131 3.1 paragraph 3:
450 * "The client _broadcasts_ a DHCPREQUEST message..." 462 * "The client _broadcasts_ a DHCPREQUEST message..."
451 */ 463 */
452static int send_select(uint32_t xid, uint32_t server, uint32_t requested) 464/* NOINLINE: limit stack usage in caller */
465static NOINLINE int send_select(uint32_t xid, uint32_t server, uint32_t requested)
453{ 466{
454 struct dhcp_packet packet; 467 struct dhcp_packet packet;
455 struct in_addr addr; 468 struct in_addr addr;
456 469
470/*
471 * RFC 2131 4.3.2 DHCPREQUEST message
472 * ...
473 * If the DHCPREQUEST message contains a 'server identifier'
474 * option, the message is in response to a DHCPOFFER message.
475 * Otherwise, the message is a request to verify or extend an
476 * existing lease. If the client uses a 'client identifier'
477 * in a DHCPREQUEST message, it MUST use that same 'client identifier'
478 * in all subsequent messages. If the client included a list
479 * of requested parameters in a DHCPDISCOVER message, it MUST
480 * include that list in all subsequent messages.
481 */
482 /* Fill in: op, htype, hlen, cookie, chaddr fields,
483 * random xid field (we override it below),
484 * client-id option (unless -C), message type option:
485 */
457 init_packet(&packet, DHCPREQUEST); 486 init_packet(&packet, DHCPREQUEST);
487
458 packet.xid = xid; 488 packet.xid = xid;
459 udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); 489 udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested);
490
460 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); 491 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server);
492
493 /* Add options: maxsize,
494 * optionally: hostname, fqdn, vendorclass,
495 * "param req" option according to -O, and options specified with -x
496 */
461 add_client_options(&packet); 497 add_client_options(&packet);
462 498
463 addr.s_addr = requested; 499 addr.s_addr = requested;
@@ -466,13 +502,38 @@ static int send_select(uint32_t xid, uint32_t server, uint32_t requested)
466} 502}
467 503
468/* Unicast or broadcast a DHCP renew message */ 504/* Unicast or broadcast a DHCP renew message */
469static int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr) 505/* NOINLINE: limit stack usage in caller */
506static NOINLINE int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr)
470{ 507{
471 struct dhcp_packet packet; 508 struct dhcp_packet packet;
472 509
510/*
511 * RFC 2131 4.3.2 DHCPREQUEST message
512 * ...
513 * DHCPREQUEST generated during RENEWING state:
514 *
515 * 'server identifier' MUST NOT be filled in, 'requested IP address'
516 * option MUST NOT be filled in, 'ciaddr' MUST be filled in with
517 * client's IP address. In this situation, the client is completely
518 * configured, and is trying to extend its lease. This message will
519 * be unicast, so no relay agents will be involved in its
520 * transmission. Because 'giaddr' is therefore not filled in, the
521 * DHCP server will trust the value in 'ciaddr', and use it when
522 * replying to the client.
523 */
524 /* Fill in: op, htype, hlen, cookie, chaddr fields,
525 * random xid field (we override it below),
526 * client-id option (unless -C), message type option:
527 */
473 init_packet(&packet, DHCPREQUEST); 528 init_packet(&packet, DHCPREQUEST);
529
474 packet.xid = xid; 530 packet.xid = xid;
475 packet.ciaddr = ciaddr; 531 packet.ciaddr = ciaddr;
532
533 /* Add options: maxsize,
534 * optionally: hostname, fqdn, vendorclass,
535 * "param req" option according to -O, and options specified with -x
536 */
476 add_client_options(&packet); 537 add_client_options(&packet);
477 538
478 bb_info_msg("Sending renew..."); 539 bb_info_msg("Sending renew...");
@@ -485,13 +546,25 @@ static int send_renew(uint32_t xid, uint32_t server, uint32_t ciaddr)
485 546
486#if ENABLE_FEATURE_UDHCPC_ARPING 547#if ENABLE_FEATURE_UDHCPC_ARPING
487/* Broadcast a DHCP decline message */ 548/* Broadcast a DHCP decline message */
488static int send_decline(uint32_t xid, uint32_t server, uint32_t requested) 549/* NOINLINE: limit stack usage in caller */
550static NOINLINE int send_decline(uint32_t xid, uint32_t server, uint32_t requested)
489{ 551{
490 struct dhcp_packet packet; 552 struct dhcp_packet packet;
491 553
554 /* Fill in: op, htype, hlen, cookie, chaddr, random xid fields,
555 * client-id option (unless -C), message type option:
556 */
492 init_packet(&packet, DHCPDECLINE); 557 init_packet(&packet, DHCPDECLINE);
558
559 /* RFC 2131 says DHCPDECLINE's xid is randomly selected by client,
560 * but in case the server is buggy and wants DHCPDECLINE's xid
561 * to match the xid which started entire handshake,
562 * we use the same xid we used in initial DHCPDISCOVER:
563 */
493 packet.xid = xid; 564 packet.xid = xid;
565 /* DHCPDECLINE uses "requested ip", not ciaddr, to store offered IP */
494 udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested); 566 udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested);
567
495 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); 568 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server);
496 569
497 bb_info_msg("Sending decline..."); 570 bb_info_msg("Sending decline...");
@@ -504,8 +577,12 @@ static int send_release(uint32_t server, uint32_t ciaddr)
504{ 577{
505 struct dhcp_packet packet; 578 struct dhcp_packet packet;
506 579
580 /* Fill in: op, htype, hlen, cookie, chaddr, random xid fields,
581 * client-id option (unless -C), message type option:
582 */
507 init_packet(&packet, DHCPRELEASE); 583 init_packet(&packet, DHCPRELEASE);
508 packet.xid = random_xid(); 584
585 /* DHCPRELEASE uses ciaddr, not "requested ip", to store IP being released */
509 packet.ciaddr = ciaddr; 586 packet.ciaddr = ciaddr;
510 587
511 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server); 588 udhcp_add_simple_option(&packet, DHCP_SERVER_ID, server);
@@ -515,6 +592,7 @@ static int send_release(uint32_t server, uint32_t ciaddr)
515} 592}
516 593
517/* Returns -1 on errors that are fatal for the socket, -2 for those that aren't */ 594/* Returns -1 on errors that are fatal for the socket, -2 for those that aren't */
595/* NOINLINE: limit stack usage in caller */
518static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) 596static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd)
519{ 597{
520 int bytes; 598 int bytes;
@@ -765,12 +843,97 @@ static void client_background(void)
765} 843}
766#endif 844#endif
767 845
846//usage:#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
847//usage:# define IF_UDHCP_VERBOSE(...) __VA_ARGS__
848//usage:#else
849//usage:# define IF_UDHCP_VERBOSE(...)
850//usage:#endif
851//usage:#define udhcpc_trivial_usage
852//usage: "[-fbnq"IF_UDHCP_VERBOSE("v")"oCR] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]\n"
853//usage: " [-H HOSTNAME] [-V VENDOR] [-x OPT:VAL]... [-O OPT]..." IF_FEATURE_UDHCP_PORT(" [-P N]")
854//usage:#define udhcpc_full_usage "\n"
855//usage: IF_LONG_OPTS(
856//usage: "\n -i,--interface IFACE Interface to use (default eth0)"
857//usage: "\n -p,--pidfile FILE Create pidfile"
858//usage: "\n -s,--script PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")"
859//usage: "\n -t,--retries N Send up to N discover packets"
860//usage: "\n -T,--timeout N Pause between packets (default 3 seconds)"
861//usage: "\n -A,--tryagain N Wait N seconds after failure (default 20)"
862//usage: "\n -f,--foreground Run in foreground"
863//usage: USE_FOR_MMU(
864//usage: "\n -b,--background Background if lease is not obtained"
865//usage: )
866//usage: "\n -n,--now Exit if lease is not obtained"
867//usage: "\n -q,--quit Exit after obtaining lease"
868//usage: "\n -R,--release Release IP on exit"
869//usage: "\n -S,--syslog Log to syslog too"
870//usage: IF_FEATURE_UDHCP_PORT(
871//usage: "\n -P,--client-port N Use port N (default 68)"
872//usage: )
873//usage: IF_FEATURE_UDHCPC_ARPING(
874//usage: "\n -a,--arping Use arping to validate offered address"
875//usage: )
876//usage: "\n -O,--request-option OPT Request option OPT from server (cumulative)"
877//usage: "\n -o,--no-default-options Don't request any options (unless -O is given)"
878//usage: "\n -r,--request IP Request this IP address"
879//usage: "\n -x OPT:VAL Include option OPT in sent packets (cumulative)"
880//usage: "\n Examples of string, numeric, and hex byte opts:"
881//usage: "\n -x hostname:bbox - option 12"
882//usage: "\n -x lease:3600 - option 51 (lease time)"
883//usage: "\n -x 0x3d:0100BEEFC0FFEE - option 61 (client id)"
884//usage: "\n -F,--fqdn NAME Ask server to update DNS mapping for NAME"
885//usage: "\n -H,-h,--hostname NAME Send NAME as client hostname (default none)"
886//usage: "\n -V,--vendorclass VENDOR Vendor identifier (default 'udhcp VERSION')"
887//usage: "\n -C,--clientid-none Don't send MAC as client identifier"
888//usage: IF_UDHCP_VERBOSE(
889//usage: "\n -v Verbose"
890//usage: )
891//usage: )
892//usage: IF_NOT_LONG_OPTS(
893//usage: "\n -i IFACE Interface to use (default eth0)"
894//usage: "\n -p FILE Create pidfile"
895//usage: "\n -s PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")"
896//usage: "\n -t N Send up to N discover packets"
897//usage: "\n -T N Pause between packets (default 3 seconds)"
898//usage: "\n -A N Wait N seconds (default 20) after failure"
899//usage: "\n -f Run in foreground"
900//usage: USE_FOR_MMU(
901//usage: "\n -b Background if lease is not obtained"
902//usage: )
903//usage: "\n -n Exit if lease is not obtained"
904//usage: "\n -q Exit after obtaining lease"
905//usage: "\n -R Release IP on exit"
906//usage: "\n -S Log to syslog too"
907//usage: IF_FEATURE_UDHCP_PORT(
908//usage: "\n -P N Use port N (default 68)"
909//usage: )
910//usage: IF_FEATURE_UDHCPC_ARPING(
911//usage: "\n -a Use arping to validate offered address"
912//usage: )
913//usage: "\n -O OPT Request option OPT from server (cumulative)"
914//usage: "\n -o Don't request any options (unless -O is given)"
915//usage: "\n -r IP Request this IP address"
916//usage: "\n -x OPT:VAL Include option OPT in sent packets (cumulative)"
917//usage: "\n Examples of string, numeric, and hex byte opts:"
918//usage: "\n -x hostname:bbox - option 12"
919//usage: "\n -x lease:3600 - option 51 (lease time)"
920//usage: "\n -x 0x3d:0100BEEFC0FFEE - option 61 (client id)"
921//usage: "\n -F NAME Ask server to update DNS mapping for NAME"
922//usage: "\n -H,-h NAME Send NAME as client hostname (default none)"
923//usage: "\n -V VENDOR Vendor identifier (default 'udhcp VERSION')"
924//usage: "\n -C Don't send MAC as client identifier"
925//usage: IF_UDHCP_VERBOSE(
926//usage: "\n -v Verbose"
927//usage: )
928//usage: )
929
768int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 930int udhcpc_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
769int udhcpc_main(int argc UNUSED_PARAM, char **argv) 931int udhcpc_main(int argc UNUSED_PARAM, char **argv)
770{ 932{
771 uint8_t *temp, *message; 933 uint8_t *temp, *message;
772 const char *str_c, *str_V, *str_h, *str_F, *str_r; 934 const char *str_V, *str_h, *str_F, *str_r;
773 IF_FEATURE_UDHCP_PORT(char *str_P;) 935 IF_FEATURE_UDHCP_PORT(char *str_P;)
936 void *clientid_mac_ptr;
774 llist_t *list_O = NULL; 937 llist_t *list_O = NULL;
775 llist_t *list_x = NULL; 938 llist_t *list_x = NULL;
776 int tryagain_timeout = 20; 939 int tryagain_timeout = 20;
@@ -792,7 +955,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
792 955
793#if ENABLE_LONG_OPTS 956#if ENABLE_LONG_OPTS
794 static const char udhcpc_longopts[] ALIGN1 = 957 static const char udhcpc_longopts[] ALIGN1 =
795 "clientid\0" Required_argument "c"
796 "clientid-none\0" No_argument "C" 958 "clientid-none\0" No_argument "C"
797 "vendorclass\0" Required_argument "V" 959 "vendorclass\0" Required_argument "V"
798 "hostname\0" Required_argument "H" 960 "hostname\0" Required_argument "H"
@@ -818,29 +980,28 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
818 ; 980 ;
819#endif 981#endif
820 enum { 982 enum {
821 OPT_c = 1 << 0, 983 OPT_C = 1 << 0,
822 OPT_C = 1 << 1, 984 OPT_V = 1 << 1,
823 OPT_V = 1 << 2, 985 OPT_H = 1 << 2,
824 OPT_H = 1 << 3, 986 OPT_h = 1 << 3,
825 OPT_h = 1 << 4, 987 OPT_F = 1 << 4,
826 OPT_F = 1 << 5, 988 OPT_i = 1 << 5,
827 OPT_i = 1 << 6, 989 OPT_n = 1 << 6,
828 OPT_n = 1 << 7, 990 OPT_p = 1 << 7,
829 OPT_p = 1 << 8, 991 OPT_q = 1 << 8,
830 OPT_q = 1 << 9, 992 OPT_R = 1 << 9,
831 OPT_R = 1 << 10, 993 OPT_r = 1 << 10,
832 OPT_r = 1 << 11, 994 OPT_s = 1 << 11,
833 OPT_s = 1 << 12, 995 OPT_T = 1 << 12,
834 OPT_T = 1 << 13, 996 OPT_t = 1 << 13,
835 OPT_t = 1 << 14, 997 OPT_S = 1 << 14,
836 OPT_S = 1 << 15, 998 OPT_A = 1 << 15,
837 OPT_A = 1 << 16, 999 OPT_O = 1 << 16,
838 OPT_O = 1 << 17, 1000 OPT_o = 1 << 17,
839 OPT_o = 1 << 18, 1001 OPT_x = 1 << 18,
840 OPT_x = 1 << 19, 1002 OPT_f = 1 << 19,
841 OPT_f = 1 << 20,
842/* The rest has variable bit positions, need to be clever */ 1003/* The rest has variable bit positions, need to be clever */
843 OPTBIT_f = 20, 1004 OPTBIT_f = 19,
844 USE_FOR_MMU( OPTBIT_b,) 1005 USE_FOR_MMU( OPTBIT_b,)
845 IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,) 1006 IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,)
846 IF_FEATURE_UDHCP_PORT( OPTBIT_P,) 1007 IF_FEATURE_UDHCP_PORT( OPTBIT_P,)
@@ -849,7 +1010,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
849 IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,) 1010 IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,)
850 }; 1011 };
851 1012
852 /* Default options. */ 1013 /* Default options */
853 IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;) 1014 IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;)
854 IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;) 1015 IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;)
855 client_config.interface = "eth0"; 1016 client_config.interface = "eth0";
@@ -857,19 +1018,19 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
857 str_V = "udhcp "BB_VER; 1018 str_V = "udhcp "BB_VER;
858 1019
859 /* Parse command line */ 1020 /* Parse command line */
860 /* Cc: mutually exclusive; O,x: list; -T,-t,-A take numeric param */ 1021 /* O,x: list; -T,-t,-A take numeric param */
861 opt_complementary = "c--C:C--c:O::x::T+:t+:A+" 1022 opt_complementary = "O::x::T+:t+:A+"
862#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1 1023#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
863 ":vv" 1024 ":vv"
864#endif 1025#endif
865 ; 1026 ;
866 IF_LONG_OPTS(applet_long_options = udhcpc_longopts;) 1027 IF_LONG_OPTS(applet_long_options = udhcpc_longopts;)
867 opt = getopt32(argv, "c:CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:f" 1028 opt = getopt32(argv, "CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:f"
868 USE_FOR_MMU("b") 1029 USE_FOR_MMU("b")
869 IF_FEATURE_UDHCPC_ARPING("a") 1030 IF_FEATURE_UDHCPC_ARPING("a")
870 IF_FEATURE_UDHCP_PORT("P:") 1031 IF_FEATURE_UDHCP_PORT("P:")
871 "v" 1032 "v"
872 , &str_c, &str_V, &str_h, &str_h, &str_F 1033 , &str_V, &str_h, &str_h, &str_F
873 , &client_config.interface, &client_config.pidfile, &str_r /* i,p */ 1034 , &client_config.interface, &client_config.pidfile, &str_r /* i,p */
874 , &client_config.script /* s */ 1035 , &client_config.script /* s */
875 , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */ 1036 , &discover_timeout, &discover_retries, &tryagain_timeout /* T,t,A */
@@ -931,13 +1092,13 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
931 return 1; 1092 return 1;
932 } 1093 }
933 1094
934 if (opt & OPT_c) { 1095 clientid_mac_ptr = NULL;
935 client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, str_c, 0); 1096 if (!(opt & OPT_C) && !udhcp_find_option(client_config.options, DHCP_CLIENT_ID)) {
936 } else if (!(opt & OPT_C)) { 1097 /* not suppressed and not set, set the default client ID */
937 /* not set and not suppressed, set the default client ID */
938 client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, "", 7); 1098 client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, "", 7);
939 client_config.clientid[OPT_DATA] = 1; /* type: ethernet */ 1099 client_config.clientid[OPT_DATA] = 1; /* type: ethernet */
940 memcpy(client_config.clientid + OPT_DATA+1, client_config.client_mac, 6); 1100 clientid_mac_ptr = client_config.clientid + OPT_DATA+1;
1101 memcpy(clientid_mac_ptr, client_config.client_mac, 6);
941 } 1102 }
942 if (str_V[0] != '\0') 1103 if (str_V[0] != '\0')
943 client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, str_V, 0); 1104 client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, str_V, 0);
@@ -1015,6 +1176,21 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1015 * resend discover/renew/whatever 1176 * resend discover/renew/whatever
1016 */ 1177 */
1017 if (retval == 0) { 1178 if (retval == 0) {
1179 /* When running on a bridge, the ifindex may have changed
1180 * (e.g. if member interfaces were added/removed
1181 * or if the status of the bridge changed).
1182 * Refresh ifindex and client_mac:
1183 */
1184 if (udhcp_read_interface(client_config.interface,
1185 &client_config.ifindex,
1186 NULL,
1187 client_config.client_mac)
1188 ) {
1189 return 1; /* iface is gone? */
1190 }
1191 if (clientid_mac_ptr)
1192 memcpy(clientid_mac_ptr, client_config.client_mac, 6);
1193
1018 /* We will restart the wait in any case */ 1194 /* We will restart the wait in any case */
1019 already_waited_sec = 0; 1195 already_waited_sec = 0;
1020 1196
@@ -1174,7 +1350,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1174 1350
1175 /* Ignore packets that aren't for us */ 1351 /* Ignore packets that aren't for us */
1176 if (packet.hlen != 6 1352 if (packet.hlen != 6
1177 || memcmp(packet.chaddr, client_config.client_mac, 6) 1353 || memcmp(packet.chaddr, client_config.client_mac, 6) != 0
1178 ) { 1354 ) {
1179//FIXME: need to also check that last 10 bytes are zero 1355//FIXME: need to also check that last 10 bytes are zero
1180 log1("chaddr does not match, ignoring packet"); // log2? 1356 log1("chaddr does not match, ignoring packet"); // log2?
@@ -1194,13 +1370,13 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1194 /* TODO: why we don't just fetch server's IP from IP header? */ 1370 /* TODO: why we don't just fetch server's IP from IP header? */
1195 temp = udhcp_get_option(&packet, DHCP_SERVER_ID); 1371 temp = udhcp_get_option(&packet, DHCP_SERVER_ID);
1196 if (!temp) { 1372 if (!temp) {
1197 bb_error_msg("no server ID in message"); 1373 bb_error_msg("no server ID, ignoring packet");
1198 continue; 1374 continue;
1199 /* still selecting - this server looks bad */ 1375 /* still selecting - this server looks bad */
1200 } 1376 }
1201 /* it IS unaligned sometimes, don't "optimize" */ 1377 /* it IS unaligned sometimes, don't "optimize" */
1202 move_from_unaligned32(server_addr, temp); 1378 move_from_unaligned32(server_addr, temp);
1203 xid = packet.xid; 1379 /*xid = packet.xid; - already is */
1204 requested_ip = packet.yiaddr; 1380 requested_ip = packet.yiaddr;
1205 1381
1206 /* enter requesting state */ 1382 /* enter requesting state */
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c
index 043220de9..f0878652c 100644
--- a/networking/udhcp/dhcpd.c
+++ b/networking/udhcp/dhcpd.c
@@ -132,7 +132,8 @@ static uint32_t select_lease_time(struct dhcp_packet *packet)
132} 132}
133 133
134/* We got a DHCP DISCOVER. Send an OFFER. */ 134/* We got a DHCP DISCOVER. Send an OFFER. */
135static void send_offer(struct dhcp_packet *oldpacket, uint32_t static_lease_nip, struct dyn_lease *lease) 135/* NOINLINE: limit stack usage in caller */
136static NOINLINE void send_offer(struct dhcp_packet *oldpacket, uint32_t static_lease_nip, struct dyn_lease *lease)
136{ 137{
137 struct dhcp_packet packet; 138 struct dhcp_packet packet;
138 uint32_t lease_time_sec; 139 uint32_t lease_time_sec;
@@ -202,7 +203,8 @@ static void send_offer(struct dhcp_packet *oldpacket, uint32_t static_lease_nip,
202 send_packet(&packet, /*force_bcast:*/ 0); 203 send_packet(&packet, /*force_bcast:*/ 0);
203} 204}
204 205
205static void send_NAK(struct dhcp_packet *oldpacket) 206/* NOINLINE: limit stack usage in caller */
207static NOINLINE void send_NAK(struct dhcp_packet *oldpacket)
206{ 208{
207 struct dhcp_packet packet; 209 struct dhcp_packet packet;
208 210
@@ -212,7 +214,8 @@ static void send_NAK(struct dhcp_packet *oldpacket)
212 send_packet(&packet, /*force_bcast:*/ 1); 214 send_packet(&packet, /*force_bcast:*/ 1);
213} 215}
214 216
215static void send_ACK(struct dhcp_packet *oldpacket, uint32_t yiaddr) 217/* NOINLINE: limit stack usage in caller */
218static NOINLINE void send_ACK(struct dhcp_packet *oldpacket, uint32_t yiaddr)
216{ 219{
217 struct dhcp_packet packet; 220 struct dhcp_packet packet;
218 uint32_t lease_time_sec; 221 uint32_t lease_time_sec;
@@ -243,7 +246,8 @@ static void send_ACK(struct dhcp_packet *oldpacket, uint32_t yiaddr)
243 } 246 }
244} 247}
245 248
246static void send_inform(struct dhcp_packet *oldpacket) 249/* NOINLINE: limit stack usage in caller */
250static NOINLINE void send_inform(struct dhcp_packet *oldpacket)
247{ 251{
248 struct dhcp_packet packet; 252 struct dhcp_packet packet;
249 253
diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c
index d8f9c5daa..2b7528cc7 100644
--- a/networking/udhcp/packet.c
+++ b/networking/udhcp/packet.c
@@ -216,19 +216,19 @@ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt,
216 packet.udp.source = htons(source_port); 216 packet.udp.source = htons(source_port);
217 packet.udp.dest = htons(dest_port); 217 packet.udp.dest = htons(dest_port);
218 /* size, excluding IP header: */ 218 /* size, excluding IP header: */
219 packet.udp.len = htons(UPD_DHCP_SIZE - padding); 219 packet.udp.len = htons(UDP_DHCP_SIZE - padding);
220 /* for UDP checksumming, ip.len is set to UDP packet len */ 220 /* for UDP checksumming, ip.len is set to UDP packet len */
221 packet.ip.tot_len = packet.udp.len; 221 packet.ip.tot_len = packet.udp.len;
222 packet.udp.check = udhcp_checksum(&packet, IP_UPD_DHCP_SIZE - padding); 222 packet.udp.check = udhcp_checksum(&packet, IP_UDP_DHCP_SIZE - padding);
223 /* but for sending, it is set to IP packet len */ 223 /* but for sending, it is set to IP packet len */
224 packet.ip.tot_len = htons(IP_UPD_DHCP_SIZE - padding); 224 packet.ip.tot_len = htons(IP_UDP_DHCP_SIZE - padding);
225 packet.ip.ihl = sizeof(packet.ip) >> 2; 225 packet.ip.ihl = sizeof(packet.ip) >> 2;
226 packet.ip.version = IPVERSION; 226 packet.ip.version = IPVERSION;
227 packet.ip.ttl = IPDEFTTL; 227 packet.ip.ttl = IPDEFTTL;
228 packet.ip.check = udhcp_checksum(&packet.ip, sizeof(packet.ip)); 228 packet.ip.check = udhcp_checksum(&packet.ip, sizeof(packet.ip));
229 229
230 udhcp_dump_packet(dhcp_pkt); 230 udhcp_dump_packet(dhcp_pkt);
231 result = sendto(fd, &packet, IP_UPD_DHCP_SIZE - padding, /*flags:*/ 0, 231 result = sendto(fd, &packet, IP_UDP_DHCP_SIZE - padding, /*flags:*/ 0,
232 (struct sockaddr *) &dest_sll, sizeof(dest_sll)); 232 (struct sockaddr *) &dest_sll, sizeof(dest_sll));
233 msg = "sendto"; 233 msg = "sendto";
234 ret_close: 234 ret_close:
diff --git a/procps/pmap.c b/procps/pmap.c
index cfa94ed82..bb5f9e7c2 100644
--- a/procps/pmap.c
+++ b/procps/pmap.c
@@ -44,7 +44,7 @@ enum {
44 44
45static void print_smaprec(struct smaprec *currec, void *data) 45static void print_smaprec(struct smaprec *currec, void *data)
46{ 46{
47 unsigned opt = (unsigned)data; 47 unsigned opt = (uintptr_t)data;
48 48
49 printf("%0" AFMT "lx ", currec->smap_start); 49 printf("%0" AFMT "lx ", currec->smap_start);
50 50
@@ -74,7 +74,7 @@ static int procps_get_maps(pid_t pid, unsigned opt)
74 74
75 memset(&total, 0, sizeof(total)); 75 memset(&total, 0, sizeof(total));
76 76
77 ret = procps_read_smaps(pid, &total, print_smaprec, (void*)opt); 77 ret = procps_read_smaps(pid, &total, print_smaprec, (void*)(uintptr_t)opt);
78 if (ret) 78 if (ret)
79 return ret; 79 return ret;
80 80
diff --git a/procps/smemcap.c b/procps/smemcap.c
index f951a5fb6..196c91f54 100644
--- a/procps/smemcap.c
+++ b/procps/smemcap.c
@@ -125,5 +125,8 @@ int smemcap_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
125 } 125 }
126 } 126 }
127 127
128 if (ENABLE_FEATURE_CLEAN_UP)
129 closedir(d);
130
128 return EXIT_SUCCESS; 131 return EXIT_SUCCESS;
129} 132}
diff --git a/scripts/mkmakefile b/scripts/mkmakefile
index 7f9d544f9..9fc51a7c9 100755
--- a/scripts/mkmakefile
+++ b/scripts/mkmakefile
@@ -31,6 +31,9 @@ all:
31 31
32Makefile:; 32Makefile:;
33 33
34\$(filter-out all Makefile,\$(MAKECMDGOALS)) %/: 34\$(filter-out all Makefile,\$(MAKECMDGOALS)):
35 \$(MAKE) -C \$(KERNELSRC) O=\$(KERNELOUTPUT) \$@
36
37%/:
35 \$(MAKE) -C \$(KERNELSRC) O=\$(KERNELOUTPUT) \$@ 38 \$(MAKE) -C \$(KERNELSRC) O=\$(KERNELOUTPUT) \$@
36EOF 39EOF
diff --git a/sysklogd/klogd.c b/sysklogd/klogd.c
index 6766b649d..0d4c2578d 100644
--- a/sysklogd/klogd.c
+++ b/sysklogd/klogd.c
@@ -132,7 +132,7 @@ int klogd_main(int argc UNUSED_PARAM, char **argv)
132 int i = 0; 132 int i = 0;
133 char *opt_c; 133 char *opt_c;
134 int opt; 134 int opt;
135 int used = 0; 135 int used;
136 136
137 opt = getopt32(argv, "c:n", &opt_c); 137 opt = getopt32(argv, "c:n", &opt_c);
138 if (opt & OPT_LEVEL) { 138 if (opt & OPT_LEVEL) {
@@ -159,6 +159,7 @@ int klogd_main(int argc UNUSED_PARAM, char **argv)
159 159
160 syslog(LOG_NOTICE, "klogd started: %s", bb_banner); 160 syslog(LOG_NOTICE, "klogd started: %s", bb_banner);
161 161
162 used = 0;
162 while (!bb_got_signal) { 163 while (!bb_got_signal) {
163 int n; 164 int n;
164 int priority; 165 int priority;
@@ -175,22 +176,22 @@ int klogd_main(int argc UNUSED_PARAM, char **argv)
175 } 176 }
176 start[n] = '\0'; 177 start[n] = '\0';
177 178
178 /* klogctl buffer parsing modelled after code in dmesg.c */
179 /* Process each newline-terminated line in the buffer */ 179 /* Process each newline-terminated line in the buffer */
180 start = log_buffer; 180 start = log_buffer;
181 while (1) { 181 while (1) {
182 char *newline = strchrnul(start, '\n'); 182 char *newline = strchrnul(start, '\n');
183 183
184 if (*newline == '\0') { 184 if (*newline == '\0') {
185 /* This line is incomplete... */ 185 /* This line is incomplete */
186 if (start != log_buffer) { 186
187 /* move it to the front of the buffer */ 187 /* move it to the front of the buffer */
188 overlapping_strcpy(log_buffer, start); 188 overlapping_strcpy(log_buffer, start);
189 used = newline - start; 189 used = newline - start;
190 /* don't log it yet */ 190 if (used < KLOGD_LOGBUF_SIZE-1) {
191 /* buffer isn't full */
191 break; 192 break;
192 } 193 }
193 /* ...but if buffer is full, log it anyway */ 194 /* buffer is full, log it anyway */
194 used = 0; 195 used = 0;
195 newline = NULL; 196 newline = NULL;
196 } else { 197 } else {
diff --git a/util-linux/dmesg.c b/util-linux/dmesg.c
index 06a03d3fb..6e43a22f5 100644
--- a/util-linux/dmesg.c
+++ b/util-linux/dmesg.c
@@ -45,20 +45,25 @@ int dmesg_main(int argc UNUSED_PARAM, char **argv)
45 if (len == 0) 45 if (len == 0)
46 return EXIT_SUCCESS; 46 return EXIT_SUCCESS;
47 47
48 /* Skip <#> at the start of lines, and make sure we end with a newline */
49 48
50 if (ENABLE_FEATURE_DMESG_PRETTY) { 49 if (ENABLE_FEATURE_DMESG_PRETTY) {
51 int last = '\n'; 50 int last = '\n';
52 int in = 0; 51 int in = 0;
53 52
54 do { 53 /* Skip <#> at the start of lines */
55 if (last == '\n' && buf[in] == '<') 54 while (1) {
55 if (last == '\n' && buf[in] == '<') {
56 in += 3; 56 in += 3;
57 else { 57 if (in >= len)
58 last = buf[in++]; 58 break;
59 bb_putchar(last);
60 } 59 }
61 } while (in < len); 60 last = buf[in];
61 putchar(last);
62 in++;
63 if (in >= len)
64 break;
65 }
66 /* Make sure we end with a newline */
62 if (last != '\n') 67 if (last != '\n')
63 bb_putchar('\n'); 68 bb_putchar('\n');
64 } else { 69 } else {