diff options
author | David E. O'Brien <obrien@FreeBSD.org> | 2013-02-08 16:10:16 +0000 |
---|---|---|
committer | David E. O'Brien <obrien@FreeBSD.org> | 2013-02-08 16:10:16 +0000 |
commit | d9a447559bc04121f7c6682e64abe67efa154864 (patch) | |
tree | b2f038222ff8a70f687652441df00d2b564c8abe /sbin | |
parent | 3cbf5f97aafc2b249c509ee1162c47c9b28e591e (diff) | |
parent | fbda3d5daeeb730a49d025b614b35a32f0319718 (diff) | |
download | src-d9a447559bc04121f7c6682e64abe67efa154864.tar.gz src-d9a447559bc04121f7c6682e64abe67efa154864.zip |
Sync with HEAD.
Notes
Notes:
svn path=/projects/bmake/; revision=246555
Diffstat (limited to 'sbin')
37 files changed, 1205 insertions, 532 deletions
diff --git a/sbin/comcontrol/comcontrol.8 b/sbin/comcontrol/comcontrol.8 index 87a7630582e3..ec12dee1e4df 100644 --- a/sbin/comcontrol/comcontrol.8 +++ b/sbin/comcontrol/comcontrol.8 @@ -49,7 +49,7 @@ startup script. .Bl -tag -width /dev/ttyd? -compact .It Pa /dev/ttyd? dialin devices, hardwired terminals -.It Pa /dev/cuad? +.It Pa /dev/cuau? dialout devices .El .Sh SEE ALSO diff --git a/sbin/devd/devd.8 b/sbin/devd/devd.8 index 7377e254759c..8e332366dc9e 100644 --- a/sbin/devd/devd.8 +++ b/sbin/devd/devd.8 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 24, 2005 +.Dd January 30, 2013 .Dt DEVD 8 .Os .Sh NAME @@ -35,6 +35,7 @@ .Nm .Op Fl Ddn .Op Fl f Ar file +.Op Fl l Ar num .Sh DESCRIPTION The .Nm @@ -55,6 +56,12 @@ instead of the default If option .Fl f is specified more than once, the last file specified is used. +.It Fl l Ar num +Limit concurrent +.Pa /var/run/devd.pipe +connections to +.Ar num . +The default connection limit is 10. .It Fl n Do not process all pending events before becoming a daemon. Instead, call daemon right away. diff --git a/sbin/devd/devd.cc b/sbin/devd/devd.cc index 772471985a13..46f3623a3a6b 100644 --- a/sbin/devd/devd.cc +++ b/sbin/devd/devd.cc @@ -80,6 +80,7 @@ __FBSDID("$FreeBSD$"); #include <fcntl.h> #include <libutil.h> #include <paths.h> +#include <poll.h> #include <regex.h> #include <signal.h> #include <stdlib.h> @@ -127,7 +128,7 @@ delete_and_clear(vector<T *> &v) { typename vector<T *>::const_iterator i; - for (i = v.begin(); i != v.end(); i++) + for (i = v.begin(); i != v.end(); ++i) delete *i; v.clear(); } @@ -136,7 +137,7 @@ config cfg; event_proc::event_proc() : _prio(-1) { - // nothing + _epsvec.reserve(4); } event_proc::~event_proc() @@ -151,22 +152,22 @@ event_proc::add(eps *eps) } bool -event_proc::matches(config &c) +event_proc::matches(config &c) const { vector<eps *>::const_iterator i; - for (i = _epsvec.begin(); i != _epsvec.end(); i++) + for (i = _epsvec.begin(); i != _epsvec.end(); ++i) if (!(*i)->do_match(c)) return (false); return (true); } bool -event_proc::run(config &c) +event_proc::run(config &c) const { vector<eps *>::const_iterator i; - for (i = _epsvec.begin(); i != _epsvec.end(); i++) + for (i = _epsvec.begin(); i != _epsvec.end(); ++i) if (!(*i)->do_action(c)) return (false); return (true); @@ -240,26 +241,18 @@ my_system(const char *command) bool action::do_action(config &c) { - string s = c.expand_string(_cmd); + string s = c.expand_string(_cmd.c_str()); if (Dflag) fprintf(stderr, "Executing '%s'\n", s.c_str()); my_system(s.c_str()); return (true); } -match::match(config &c, const char *var, const char *re) - : _var(var) +match::match(config &c, const char *var, const char *re) : + _inv(re[0] == '!'), + _var(var), + _re(c.expand_string(_inv ? re + 1 : re, "^", "$")) { - _re = "^"; - if (!c.expand_string(string(re)).empty() && - c.expand_string(string(re)).at(0) == '!') { - _re.append(c.expand_string(string(re)).substr(1)); - _inv = 1; - } else { - _re.append(c.expand_string(string(re))); - _inv = 0; - } - _re.append("$"); regcomp(&_regex, _re.c_str(), REG_EXTENDED | REG_NOSUB | REG_ICASE); } @@ -301,7 +294,7 @@ media::media(config &, const char *var, const char *type) { -1, "unknown" }, { 0, NULL }, }; - for (int i = 0; media_types[i].ifmt_string != NULL; i++) + for (int i = 0; media_types[i].ifmt_string != NULL; ++i) if (strcasecmp(type, media_types[i].ifmt_string) == 0) { _type = media_types[i].ifmt_word; break; @@ -436,7 +429,7 @@ config::parse_files_in_dir(const char *dirname) class epv_greater { public: - int operator()(event_proc *const&l1, event_proc *const&l2) + int operator()(event_proc *const&l1, event_proc *const&l2) const { return (l1->get_priority() > l2->get_priority()); } @@ -445,7 +438,7 @@ public: void config::sort_vector(vector<event_proc *> &v) { - sort(v.begin(), v.end(), epv_greater()); + stable_sort(v.begin(), v.end(), epv_greater()); } void @@ -454,7 +447,7 @@ config::parse(void) vector<string>::const_iterator i; parse_one_file(configfile); - for (i = _dir_list.begin(); i != _dir_list.end(); i++) + for (i = _dir_list.begin(); i != _dir_list.end(); ++i) parse_files_in_dir((*i).c_str()); sort_vector(_attach_list); sort_vector(_detach_list); @@ -569,7 +562,7 @@ config::get_variable(const string &var) { vector<var_list *>::reverse_iterator i; - for (i = _var_list_table.rbegin(); i != _var_list_table.rend(); i++) { + for (i = _var_list_table.rbegin(); i != _var_list_table.rend(); ++i) { if ((*i)->is_set(var)) return ((*i)->get_variable(var)); } @@ -577,7 +570,7 @@ config::get_variable(const string &var) } bool -config::is_id_char(char ch) +config::is_id_char(char ch) const { return (ch != '\0' && (isalpha(ch) || isdigit(ch) || ch == '_' || ch == '-')); @@ -624,24 +617,37 @@ config::expand_one(const char *&src, string &dst) do { buffer.append(src++, 1); } while (is_id_char(*src)); - buffer.append("", 1); dst.append(get_variable(buffer.c_str())); } const string -config::expand_string(const string &s) +config::expand_string(const char *src, const char *prepend, const char *append) { - const char *src; + const char *var_at; string dst; - src = s.c_str(); - while (*src) { - if (*src == '$') - expand_one(src, dst); - else - dst.append(src++, 1); + /* + * 128 bytes is enough for 2427 of 2438 expansions that happen + * while parsing config files, as tested on 2013-01-30. + */ + dst.reserve(128); + + if (prepend != NULL) + dst = prepend; + + for (;;) { + var_at = strchr(src, '$'); + if (var_at == NULL) { + dst.append(src); + break; + } + dst.append(src, var_at - src); + src = var_at; + expand_one(src, dst); } - dst.append("", 1); + + if (append != NULL) + dst.append(append); return (dst); } @@ -726,7 +732,7 @@ config::find_and_execute(char type) } if (Dflag) fprintf(stderr, "Processing %s event\n", s); - for (i = l->begin(); i != l->end(); i++) { + for (i = l->begin(); i != l->end(); ++i) { if ((*i)->matches(*this)) { (*i)->run(*this); break; @@ -815,23 +821,58 @@ create_socket(const char *name) return (fd); } +unsigned int max_clients = 10; /* Default, can be overriden on cmdline. */ +unsigned int num_clients; list<int> clients; void notify_clients(const char *data, int len) { - list<int> bad; - list<int>::const_iterator i; + list<int>::iterator i; - for (i = clients.begin(); i != clients.end(); i++) { - if (write(*i, data, len) <= 0) { - bad.push_back(*i); + /* + * Deliver the data to all clients. Throw clients overboard at the + * first sign of trouble. This reaps clients who've died or closed + * their sockets, and also clients who are alive but failing to keep up + * (or who are maliciously not reading, to consume buffer space in + * kernel memory or tie up the limited number of available connections). + */ + for (i = clients.begin(); i != clients.end(); ) { + if (write(*i, data, len) != len) { + --num_clients; close(*i); - } + i = clients.erase(i); + } else + ++i; } +} - for (i = bad.begin(); i != bad.end(); i++) - clients.erase(find(clients.begin(), clients.end(), *i)); +void +check_clients(void) +{ + int s; + struct pollfd pfd; + list<int>::iterator i; + + /* + * Check all existing clients to see if any of them have disappeared. + * Normally we reap clients when we get an error trying to send them an + * event. This check eliminates the problem of an ever-growing list of + * zombie clients because we're never writing to them on a system + * without frequent device-change activity. + */ + pfd.events = 0; + for (i = clients.begin(); i != clients.end(); ) { + pfd.fd = *i; + s = poll(&pfd, 1, 0); + if ((s < 0 && s != EINTR ) || + (s > 0 && (pfd.revents & POLLHUP))) { + --num_clients; + close(*i); + i = clients.erase(i); + } else + ++i; + } } void @@ -839,9 +880,18 @@ new_client(int fd) { int s; + /* + * First go reap any zombie clients, then accept the connection, and + * shut down the read side to stop clients from consuming kernel memory + * by sending large buffers full of data we'll never read. + */ + check_clients(); s = accept(fd, NULL, NULL); - if (s != -1) + if (s != -1) { + shutdown(s, SHUT_RD); clients.push_back(s); + ++num_clients; + } } static void @@ -852,6 +902,7 @@ event_loop(void) char buffer[DEVCTL_MAXBUF]; int once = 0; int server_fd, max_fd; + int accepting; timeval tv; fd_set fds; @@ -859,6 +910,7 @@ event_loop(void) if (fd == -1) err(1, "Can't open devctl device %s", PATH_DEVCTL); server_fd = create_socket(PIPE); + accepting = 1; max_fd = max(fd, server_fd) + 1; while (1) { if (romeo_must_die) @@ -881,15 +933,38 @@ event_loop(void) once++; } } + /* + * When we've already got the max number of clients, stop + * accepting new connections (don't put server_fd in the set), + * shrink the accept() queue to reject connections quickly, and + * poll the existing clients more often, so that we notice more + * quickly when any of them disappear to free up client slots. + */ FD_ZERO(&fds); FD_SET(fd, &fds); - FD_SET(server_fd, &fds); - rv = select(max_fd, &fds, NULL, NULL, NULL); + if (num_clients < max_clients) { + if (!accepting) { + listen(server_fd, max_clients); + accepting = 1; + } + FD_SET(server_fd, &fds); + tv.tv_sec = 60; + tv.tv_usec = 0; + } else { + if (accepting) { + listen(server_fd, 0); + accepting = 0; + } + tv.tv_sec = 2; + tv.tv_usec = 0; + } + rv = select(max_fd, &fds, NULL, NULL, &tv); if (rv == -1) { if (errno == EINTR) continue; err(1, "select"); - } + } else if (rv == 0) + check_clients(); if (FD_ISSET(fd, &fds)) { rv = read(fd, buffer, sizeof(buffer) - 1); if (rv > 0) { @@ -1008,7 +1083,8 @@ gensighand(int) static void usage() { - fprintf(stderr, "usage: %s [-Ddn] [-f file]\n", getprogname()); + fprintf(stderr, "usage: %s [-Ddn] [-l connlimit] [-f file]\n", + getprogname()); exit(1); } @@ -1037,7 +1113,7 @@ main(int argc, char **argv) int ch; check_devd_enabled(); - while ((ch = getopt(argc, argv, "Ddf:n")) != -1) { + while ((ch = getopt(argc, argv, "Ddf:l:n")) != -1) { switch (ch) { case 'D': Dflag++; @@ -1048,6 +1124,9 @@ main(int argc, char **argv) case 'f': configfile = optarg; break; + case 'l': + max_clients = MAX(1, strtoul(optarg, NULL, 0)); + break; case 'n': nflag++; break; diff --git a/sbin/devd/devd.hh b/sbin/devd/devd.hh index 1830dada87ec..a48d07b4930c 100644 --- a/sbin/devd/devd.hh +++ b/sbin/devd/devd.hh @@ -90,9 +90,9 @@ public: virtual bool do_match(config &); virtual bool do_action(config &) { return true; } private: + bool _inv; std::string _var; std::string _re; - bool _inv; regex_t _regex; }; @@ -134,8 +134,8 @@ public: int get_priority() const { return (_prio); } void set_priority(int prio) { _prio = prio; } void add(eps *); - bool matches(config &); - bool run(config &); + bool matches(config &) const; + bool run(config &) const; private: int _prio; std::vector<eps *> _epsvec; @@ -144,7 +144,7 @@ private: class config { public: - config() { _pidfile = ""; push_var_table(); } + config() : _pidfile("") { push_var_table(); } virtual ~config() { reset(); } void add_attach(int, event_proc *); void add_detach(int, event_proc *); @@ -162,7 +162,8 @@ public: void pop_var_table(); void set_variable(const char *var, const char *val); const std::string &get_variable(const std::string &var); - const std::string expand_string(const std::string &var); + const std::string expand_string(const char * var, + const char * prepend = NULL, const char * append = NULL); char *set_vars(char *); void find_and_execute(char); protected: @@ -170,7 +171,7 @@ protected: void parse_one_file(const char *fn); void parse_files_in_dir(const char *dirname); void expand_one(const char *&src, std::string &dst); - bool is_id_char(char); + bool is_id_char(char) const; bool chop_var(char *&buffer, char *&lhs, char *&rhs); private: std::vector<std::string> _dir_list; diff --git a/sbin/dump/dump.h b/sbin/dump/dump.h index 2a65865aab3d..4a8af104d4df 100644 --- a/sbin/dump/dump.h +++ b/sbin/dump/dump.h @@ -121,7 +121,7 @@ void trewind(void); void writerec(char *dp, int isspcl); void Exit(int status) __dead2; -void dumpabort(int signo); +void dumpabort(int signo) __dead2; void dump_getfstab(void); char *rawname(char *cp); diff --git a/sbin/fsck_ffs/suj.c b/sbin/fsck_ffs/suj.c index 0800a5c7b6eb..ae4748716e2d 100644 --- a/sbin/fsck_ffs/suj.c +++ b/sbin/fsck_ffs/suj.c @@ -504,7 +504,7 @@ blk_equals(struct jblkrec *brec, ino_t ino, ufs_lbn_t lbn, ufs2_daddr_t start, return (0); if (brec->jb_blkno + brec->jb_oldfrags != start) return (0); - if (brec->jb_frags != frags) + if (brec->jb_frags < frags) return (0); return (1); } @@ -551,7 +551,6 @@ blk_freemask(ufs2_daddr_t blk, ino_t ino, ufs_lbn_t lbn, int frags) brec = (struct jblkrec *)srec->sr_rec; /* * If the block overlaps but does not match - * exactly it's a new allocation. If it matches * exactly this record refers to the current * location. */ @@ -648,7 +647,8 @@ blk_free(ufs2_daddr_t bno, int mask, int frags) uint8_t *blksfree; if (debug) - printf("Freeing %d frags at blk %jd\n", frags, bno); + printf("Freeing %d frags at blk %jd mask 0x%x\n", + frags, bno, mask); cg = dtog(fs, bno); sc = cg_lookup(cg); cgp = sc->sc_cgp; @@ -1143,12 +1143,8 @@ ino_adjblks(struct suj_ino *sino) static void blk_free_visit(ino_t ino, ufs_lbn_t lbn, ufs2_daddr_t blk, int frags) { - int mask; - mask = blk_freemask(blk, ino, lbn, frags); - if (debug) - printf("blk %jd freemask 0x%X\n", blk, mask); - blk_free(blk, mask, frags); + blk_free(blk, blk_freemask(blk, ino, lbn, frags), frags); } /* @@ -1163,8 +1159,6 @@ blk_free_lbn(ufs2_daddr_t blk, ino_t ino, ufs_lbn_t lbn, int frags, int follow) int mask; mask = blk_freemask(blk, ino, lbn, frags); - if (debug) - printf("blk %jd freemask 0x%X\n", blk, mask); resid = 0; if (lbn <= -NDADDR && follow && mask == 0) indir_visit(ino, lbn, blk, &resid, blk_free_visit, VISIT_INDIR); @@ -2334,6 +2328,10 @@ suj_prune(void) } if (newseq != oldseq) { + TAILQ_FOREACH(seg, &allsegs, ss_next) { + printf("%jd, ", seg->ss_rec.jsr_seq); + } + printf("\n"); err_suj("Journal file sequence mismatch %jd != %jd\n", newseq, oldseq); } diff --git a/sbin/geom/class/journal/geom_journal_ufs.c b/sbin/geom/class/journal/geom_journal_ufs.c index c847a880d64b..07d1922df81a 100644 --- a/sbin/geom/class/journal/geom_journal_ufs.c +++ b/sbin/geom/class/journal/geom_journal_ufs.c @@ -73,6 +73,6 @@ g_journal_ufs_using_last_sector(const char *prov) /* Provider size in 512 bytes blocks. */ psize = g_get_mediasize(prov) / DEV_BSIZE; /* File system size in 512 bytes blocks. */ - fssize = fsbtodb(fs, dbtofsb(fs, psize)); - return (psize == fssize); + fssize = fsbtodb(fs, fs->fs_size); + return (psize <= fssize); } diff --git a/sbin/geom/class/part/gpart.8 b/sbin/geom/class/part/gpart.8 index 7a91d3dbc07c..8843e5324954 100644 --- a/sbin/geom/class/part/gpart.8 +++ b/sbin/geom/class/part/gpart.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 19, 2012 +.Dd January 25, 2013 .Dt GPART 8 .Os .Sh NAME @@ -453,8 +453,14 @@ about its use. .El .\" ==== SHOW ==== .It Cm show -Show the current partition information of the specified geoms -or all geoms if none are specified. +Show current partition information for the specified geoms, or all +geoms if none are specified. +The default output includes the logical starting block of each +partition, the partition size in blocks, the partition index number, +the partition type, and a human readable partition size. +Block sizes and locations are based on the device's Sectorsize +as shown by +.Cm gpart list . Additional options include: .Bl -tag -width 10n .It Fl l @@ -801,34 +807,51 @@ Both types of bootstrap code are used to boot from the GUID Partition Table. First, a protective MBR is embedded into the first disk sector from the .Pa /boot/pmbr image. -It searches the GPT +It searches through the GPT for a .Cm freebsd-boot partition (see the .Sx "PARTITION TYPES" -section) in the GPT and runs the next bootstrap stage from it. +section) and runs the next bootstrap stage from it. The .Cm freebsd-boot partition should be smaller than 545 KB. +It can be located either before or after other +.Fx +partitions on the disk. There are two variants of bootstrap code to write to this partition: .Pa /boot/gptboot and .Pa /boot/gptzfsboot . .Pa /boot/gptboot is used to boot from UFS. -It searches +It searches through +.Cm freebsd-ufs +partitions in the GPT and boots from the first one with the +.Cm bootonce +attribute set. +If that attribute is not found, +.Pa /boot/gptboot +boots from the first .Cm freebsd-ufs -GPT partitions and starts +partition with the +.Cm bootme +attribute set. +If neither attribute is found, +.Pa /boot/gptboot +boots from the first +.Cm freebsd-ufs +partition. .Pa /boot/loader .Pq the third bootstrap stage -if found. -The +is loaded from the first partition that matches these conditions. .Pa /boot/gptzfsboot is used to boot from ZFS. -It searches +It searches through the GPT for .Cm freebsd-zfs -GPT partitions and starts +partitions, trying to detect ZFS pools. +After all pools are detected, .Pa /boot/zfsloader -if found. +is started from the first one found. .Pp The VTOC8 scheme does not support embedding bootstrap code. Instead, the 8 KBytes bootstrap code image @@ -919,7 +942,7 @@ and .Cm list will report about corrupt tables. .Pp -If the size of the device has changed (e.g.\& volume expansion) the +If the size of the device has changed (e.g.,\& volume expansion) the secondary GPT header will no longer be located in the last sector. This is not a metadata corruption, but it is dangerous because any corruption of the primary GPT will lead to loss of the partition table. @@ -939,7 +962,7 @@ The GEOM PART class can detect the same partition table visible through different GEOM providers, and some of them will be marked as corrupt. Be careful when choosing a provider for recovery. If you choose incorrectly you can destroy the metadata of another GEOM class, -e.g.\& GEOM MIRROR or GEOM LABEL. +e.g.,\& GEOM MIRROR or GEOM LABEL. .Sh SYSCTL VARIABLES The following .Xr sysctl 8 @@ -979,14 +1002,14 @@ This may break a mirrored volume and lead to data damage. Exit status is 0 on success, and 1 if the command fails. .Sh EXAMPLES Create a GPT scheme on -.Pa ad0 : +.Pa ada0 : .Bd -literal -offset indent -/sbin/gpart create -s GPT ad0 +/sbin/gpart create -s GPT ada0 .Ed .Pp Embed GPT bootstrap code into a protective MBR: .Bd -literal -offset indent -/sbin/gpart bootcode -b /boot/pmbr ad0 +/sbin/gpart bootcode -b /boot/pmbr ada0 .Ed .Pp Create a dedicated @@ -1011,15 +1034,15 @@ aligned on a 64 kB boundary without the need to specify an explicit offset or alignment. The boot partition itself is aligned on a 4 kB boundary. .Bd -literal -offset indent -/sbin/gpart add -b 40 -s 88 -t freebsd-boot ad0 -/sbin/gpart bootcode -p /boot/gptboot -i 1 ad0 +/sbin/gpart add -b 40 -s 88 -t freebsd-boot ada0 +/sbin/gpart bootcode -p /boot/gptboot -i 1 ada0 .Ed .Pp Create a 512MB-sized .Cm freebsd-ufs partition to contain a UFS filesystem from which the system can boot. .Bd -literal -offset indent -/sbin/gpart add -s 512M -t freebsd-ufs ad0 +/sbin/gpart add -s 512M -t freebsd-ufs ada0 .Ed .Pp Create an MBR scheme on diff --git a/sbin/geom/class/raid/graid.8 b/sbin/geom/class/raid/graid.8 index 630cd018e621..ed33e00ae977 100644 --- a/sbin/geom/class/raid/graid.8 +++ b/sbin/geom/class/raid/graid.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 13, 2012 +.Dd January 16, 2013 .Dt GRAID 8 .Os .Sh NAME @@ -274,7 +274,6 @@ complete it there. Do not run GEOM RAID class on migrating volumes under pain of possible data corruption! .Sh 2TiB BARRIERS -Promise metadata format does not support disks above 2TiB. NVIDIA metadata format does not support volumes above 2TiB. .Sh SYSCTL VARIABLES The following diff --git a/sbin/geom/class/raid3/geom_raid3.c b/sbin/geom/class/raid3/geom_raid3.c index 3f037cdbec85..cd0aa65b14c5 100644 --- a/sbin/geom/class/raid3/geom_raid3.c +++ b/sbin/geom/class/raid3/geom_raid3.c @@ -76,7 +76,7 @@ struct g_command class_commands[] = { { "insert", G_FLAG_VERBOSE, NULL, { { 'h', "hardcode", NULL, G_TYPE_BOOL }, - { 'n', "number", NULL, G_TYPE_NUMBER }, + { 'n', "number", G_VAL_OPTIONAL, G_TYPE_NUMBER }, G_OPT_SENTINEL }, "[-hv] <-n number> name prov" diff --git a/sbin/geom/class/raid3/graid3.8 b/sbin/geom/class/raid3/graid3.8 index f396cc3e9d10..a82d3882e8a2 100644 --- a/sbin/geom/class/raid3/graid3.8 +++ b/sbin/geom/class/raid3/graid3.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 5, 2010 +.Dd January 15, 2012 .Dt GRAID3 8 .Os .Sh NAME @@ -53,7 +53,7 @@ .Nm .Cm insert .Op Fl hv -.Fl n Ar number +.Op Fl n Ar number .Ar name .Ar prov .Nm @@ -171,6 +171,8 @@ Add the given component to the existing array, if one of the components was removed previously with the .Cm remove command or if one component is missing and will not be connected again. +If no number is given, new component will be added instead of first missed +component. .Pp Additional options include: .Bl -tag -width ".Fl h" diff --git a/sbin/growfs/growfs.8 b/sbin/growfs/growfs.8 index 92508dac9785..664e7234dfe1 100644 --- a/sbin/growfs/growfs.8 +++ b/sbin/growfs/growfs.8 @@ -115,11 +115,16 @@ The .Nm utility first appeared in .Fx 4.4 . +The ability to resize mounted filesystems was added in +.Fx 10.0 . .Sh AUTHORS .An Christoph Herrmann Aq chm@FreeBSD.org .An Thomas-Henning von Kamptz Aq tomsoft@FreeBSD.org .An The GROWFS team Aq growfs@Tomsoft.COM .An Edward Tomasz Napierala Aq trasz@FreeBSD.org +.Sh CAVEATS +When expanding a file system mounted read-write, any writes to that file system +will be temporarily suspended until the expansion is finished. .Sh BUGS Normally .Nm diff --git a/sbin/growfs/growfs.c b/sbin/growfs/growfs.c index ad837a82f52e..745e9e975572 100644 --- a/sbin/growfs/growfs.c +++ b/sbin/growfs/growfs.c @@ -69,6 +69,7 @@ __FBSDID("$FreeBSD$"); #include <inttypes.h> #include <limits.h> #include <mntopts.h> +#include <paths.h> #include <stdlib.h> #include <stdint.h> #include <string.h> @@ -1486,6 +1487,12 @@ main(int argc, char **argv) } } + /* + * Make sure the new size is a multiple of fs_fsize; /dev/ufssuspend + * only supports fragment-aligned IO requests. + */ + size -= size % osblock.fs_fsize; + if (size <= (uint64_t)(osblock.fs_size * osblock.fs_fsize)) { humanize_number(oldsizebuf, sizeof(oldsizebuf), osblock.fs_size * osblock.fs_fsize, @@ -1525,8 +1532,9 @@ main(int argc, char **argv) if (yflag == 0 && Nflag == 0) { if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) == 0) - errx(1, "%s is mounted read-write on %s", - statfsp->f_mntfromname, statfsp->f_mntonname); + printf("Device is mounted read-write; resizing will " + "result in temporary write suspension for %s.\n", + statfsp->f_mntonname); printf("It's strongly recommended to make a backup " "before growing the file system.\n" "OK to grow filesystem on %s", device); @@ -1555,9 +1563,18 @@ main(int argc, char **argv) if (Nflag) { fso = -1; } else { - fso = open(device, O_WRONLY); - if (fso < 0) - err(1, "%s", device); + if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) == 0) { + fso = open(_PATH_UFSSUSPEND, O_RDWR); + if (fso == -1) + err(1, "unable to open %s", _PATH_UFSSUSPEND); + error = ioctl(fso, UFSSUSPEND, &statfsp->f_fsid); + if (error != 0) + err(1, "UFSSUSPEND"); + } else { + fso = open(device, O_WRONLY); + if (fso < 0) + err(1, "%s", device); + } } /* @@ -1594,17 +1611,20 @@ main(int argc, char **argv) } sblock.fs_ncg = howmany(sblock.fs_size, sblock.fs_fpg); + /* + * Allocate last cylinder group only if there is enough room + * for at least one data block. + */ if (sblock.fs_size % sblock.fs_fpg != 0 && - sblock.fs_size % sblock.fs_fpg < cgdmin(&sblock, sblock.fs_ncg)) { - /* - * The space in the new last cylinder group is too small, - * so revert back. - */ + sblock.fs_size <= cgdmin(&sblock, sblock.fs_ncg - 1)) { + humanize_number(oldsizebuf, sizeof(oldsizebuf), + (sblock.fs_size % sblock.fs_fpg) * sblock.fs_fsize, + "B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); + warnx("no room to allocate last cylinder group; " + "leaving %s unused", oldsizebuf); sblock.fs_ncg--; if (sblock.fs_magic == FS_UFS1_MAGIC) sblock.fs_old_ncyl = sblock.fs_ncg * sblock.fs_old_cpg; - printf("Warning: %jd sector(s) cannot be allocated.\n", - (intmax_t)fsbtodb(&sblock, sblock.fs_size % sblock.fs_fpg)); sblock.fs_size = sblock.fs_ncg * sblock.fs_fpg; } @@ -1627,12 +1647,17 @@ main(int argc, char **argv) close(fsi); if (fso > -1) { + if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) == 0) { + error = ioctl(fso, UFSRESUME); + if (error != 0) + err(1, "UFSRESUME"); + } error = close(fso); if (error != 0) err(1, "close"); + if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) != 0) + mount_reload(statfsp); } - if (statfsp != NULL) - mount_reload(statfsp); DBG_CLOSE; diff --git a/sbin/hastd/parse.y b/sbin/hastd/parse.y index a20b61aa1f5a..04ea7ab2513e 100644 --- a/sbin/hastd/parse.y +++ b/sbin/hastd/parse.y @@ -769,7 +769,7 @@ family_supported(int family) int sock; sock = socket(family, SOCK_STREAM, 0); - if (sock == -1 && errno == EPROTONOSUPPORT) + if (sock == -1 && errno == EAFNOSUPPORT) return (false); if (sock >= 0) (void)close(sock); diff --git a/sbin/hastd/pjdlog.h b/sbin/hastd/pjdlog.h index bae431e35cae..0f01f798bffe 100644 --- a/sbin/hastd/pjdlog.h +++ b/sbin/hastd/pjdlog.h @@ -95,7 +95,7 @@ void pjdlog_abort(const char *func, const char *file, int line, #define PJDLOG_VERIFY(expr) do { \ if (!(expr)) { \ pjdlog_abort(__func__, __FILE__, __LINE__, #expr, \ - "%s", __func__); \ + __func__); \ } \ } while (0) #define PJDLOG_RVERIFY(expr, ...) do { \ diff --git a/sbin/ifconfig/af_inet6.c b/sbin/ifconfig/af_inet6.c index d74b0d21492b..b4db0f174cd7 100644 --- a/sbin/ifconfig/af_inet6.c +++ b/sbin/ifconfig/af_inet6.c @@ -62,7 +62,6 @@ static struct in6_aliasreq in6_addreq = .ifra_lifetime = { 0, 0, ND6_INFINITE_LIFETIME, ND6_INFINITE_LIFETIME } }; static int ip6lifetime; -static void in6_fillscopeid(struct sockaddr_in6 *sin6); static int prefix(void *, int); static char *sec2str(time_t); static int explicit_prefix = 0; @@ -166,18 +165,6 @@ setip6eui64(const char *cmd, int dummy __unused, int s, } static void -in6_fillscopeid(struct sockaddr_in6 *sin6) -{ -#if defined(__KAME__) && defined(KAME_SCOPEID) - if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { - sin6->sin6_scope_id = - ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]); - sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0; - } -#endif -} - -static void in6_status(int s __unused, const struct ifaddrs *ifa) { struct sockaddr_in6 *sin, null_sin; @@ -187,7 +174,6 @@ in6_status(int s __unused, const struct ifaddrs *ifa) struct in6_addrlifetime lifetime; time_t t = time(NULL); int error; - u_int32_t scopeid; memset(&null_sin, 0, sizeof(null_sin)); @@ -217,18 +203,6 @@ in6_status(int s __unused, const struct ifaddrs *ifa) lifetime = ifr6.ifr_ifru.ifru_lifetime; close(s6); - /* XXX: embedded link local addr check */ - if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) && - *(u_short *)&sin->sin6_addr.s6_addr[2] != 0) { - u_short index; - - index = *(u_short *)&sin->sin6_addr.s6_addr[2]; - *(u_short *)&sin->sin6_addr.s6_addr[2] = 0; - if (sin->sin6_scope_id == 0) - sin->sin6_scope_id = ntohs(index); - } - scopeid = sin->sin6_scope_id; - error = getnameinfo((struct sockaddr *)sin, sin->sin6_len, addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST); if (error != 0) @@ -245,17 +219,6 @@ in6_status(int s __unused, const struct ifaddrs *ifa) if (sin != NULL && sin->sin6_family == AF_INET6) { int error; - /* XXX: embedded link local addr check */ - if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) && - *(u_short *)&sin->sin6_addr.s6_addr[2] != 0) { - u_short index; - - index = *(u_short *)&sin->sin6_addr.s6_addr[2]; - *(u_short *)&sin->sin6_addr.s6_addr[2] = 0; - if (sin->sin6_scope_id == 0) - sin->sin6_scope_id = ntohs(index); - } - error = getnameinfo((struct sockaddr *)sin, sin->sin6_len, addr_buf, sizeof(addr_buf), NULL, 0, @@ -288,8 +251,9 @@ in6_status(int s __unused, const struct ifaddrs *ifa) if ((flags6 & IN6_IFF_TEMPORARY) != 0) printf("temporary "); - if (scopeid) - printf("scopeid 0x%x ", scopeid); + if (((struct sockaddr_in6 *)(ifa->ifa_addr))->sin6_scope_id) + printf("scopeid 0x%x ", + ((struct sockaddr_in6 *)(ifa->ifa_addr))->sin6_scope_id); if (ip6lifetime && (lifetime.ia6t_preferred || lifetime.ia6t_expire)) { printf("pltime "); @@ -458,7 +422,6 @@ in6_status_tunnel(int s) return; if (sa->sa_family != AF_INET6) return; - in6_fillscopeid(&in6_ifr.ifr_addr); if (getnameinfo(sa, sa->sa_len, src, sizeof(src), 0, 0, NI_NUMERICHOST) != 0) src[0] = '\0'; @@ -467,7 +430,6 @@ in6_status_tunnel(int s) return; if (sa->sa_family != AF_INET6) return; - in6_fillscopeid(&in6_ifr.ifr_addr); if (getnameinfo(sa, sa->sa_len, dst, sizeof(dst), 0, 0, NI_NUMERICHOST) != 0) dst[0] = '\0'; @@ -511,6 +473,8 @@ static struct cmd inet6_cmds[] = { DEF_CMD("-nud", -ND6_IFF_PERFORMNUD, setnd6flags), DEF_CMD("auto_linklocal",ND6_IFF_AUTO_LINKLOCAL,setnd6flags), DEF_CMD("-auto_linklocal",-ND6_IFF_AUTO_LINKLOCAL,setnd6flags), + DEF_CMD("no_prefer_iface",ND6_IFF_NO_PREFER_IFACE,setnd6flags), + DEF_CMD("-no_prefer_iface",-ND6_IFF_NO_PREFER_IFACE,setnd6flags), DEF_CMD_ARG("pltime", setip6pltime), DEF_CMD_ARG("vltime", setip6vltime), DEF_CMD("eui64", 0, setip6eui64), diff --git a/sbin/ifconfig/af_nd6.c b/sbin/ifconfig/af_nd6.c index 654e2d97fe0b..5c46452759d1 100644 --- a/sbin/ifconfig/af_nd6.c +++ b/sbin/ifconfig/af_nd6.c @@ -58,7 +58,7 @@ static const char rcsid[] = #define MAX_SYSCTL_TRY 5 #define ND6BITS "\020\001PERFORMNUD\002ACCEPT_RTADV\003PREFER_SOURCE" \ "\004IFDISABLED\005DONT_SET_IFROUTE\006AUTO_LINKLOCAL" \ - "\007NO_RADR\020DEFAULTIF" + "\007NO_RADR\010NO_PREFER_IFACE\020DEFAULTIF" static int isnd6defif(int); void setnd6flags(const char *, int, int, const struct afswtch *); @@ -148,7 +148,7 @@ nd6_status(int s) memset(&nd, 0, sizeof(nd)); strncpy(nd.ifname, ifr.ifr_name, sizeof(nd.ifname)); if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { - if (errno != EPROTONOSUPPORT) + if (errno != EAFNOSUPPORT) warn("socket(AF_INET6, SOCK_DGRAM)"); return; } diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8 index f22cc50598ca..9c7498041852 100644 --- a/sbin/ifconfig/ifconfig.8 +++ b/sbin/ifconfig/ifconfig.8 @@ -28,7 +28,7 @@ .\" From: @(#)ifconfig.8 8.3 (Berkeley) 1/5/94 .\" $FreeBSD$ .\" -.Dd July 9, 2012 +.Dd January 10, 2013 .Dt IFCONFIG 8 .Os .Sh NAME @@ -142,7 +142,7 @@ The link-level address is specified as a series of colon-separated hex digits. This can be used to -e.g.\& set a new MAC address on an ethernet interface, though the +e.g.,\& set a new MAC address on an ethernet interface, though the mechanism used is not ethernet-specific. If the interface is already up when this option is used, it will be briefly brought down and @@ -301,7 +301,7 @@ Specify interface FIB. A FIB .Ar fib_number is assigned to all frames or packets received on that interface. -The FIB is not inherited, e.g. vlans or other sub-interfaces will use +The FIB is not inherited, e.g., vlans or other sub-interfaces will use the default FIB (0) irrespective of the parent interface's FIB. The kernel needs to be tuned to support more than the default FIB using the @@ -716,6 +716,13 @@ Set a flag to enable Neighbor Unreachability Detection. .It Cm -nud Clear a flag .Cm nud . +.It Cm no_prefer_iface +Set a flag to not prefer address on the interface as candidates of the +source address for outgoing packets, even when the interface is +outgoing interface. +.It Cm -no_prefer_iface +Clear a flag +.Cm no_prefer_iface . .El .Pp The following parameters are specific to cloning @@ -1003,7 +1010,7 @@ For example, if a device is capable of operating on channel 6 with 802.11n and 802.11g then one can specify that g-only use should be used by specifying ``6:g''. Similarly the channel width can be specified by appending it -with ``/''; e.g. ``6/40'' specifies a 40MHz wide channel, +with ``/''; e.g., ``6/40'' specifies a 40MHz wide channel, These attributes can be combined as in: ``6:ht/40''. The full set of flags specified following a ``:'' are: .Cm a @@ -1036,7 +1043,7 @@ and In addition, a 40MHz HT channel specification may include the location of the extension channel by appending ``+'' or ``-'' for above and below, -respectively; e.g. ``2437:ht/40+'' specifies 40MHz wide HT operation +respectively; e.g., ``2437:ht/40+'' specifies 40MHz wide HT operation with the center channel at frequency 2437 and the extension channel above. .It Cm country Ar name Set the country code to use in calculating the regulatory constraints @@ -1046,7 +1053,7 @@ will operation on the channels, and the maximum transmit power that can be used on a channel are defined by this setting. Country/Region codes are specified as a 2-character abbreviation defined by ISO 3166 or using a longer, but possibly ambiguous, spelling; -e.g. "ES" and "Spain". +e.g., "ES" and "Spain". The set of country codes are taken from /etc/regdomain.xml and can also be viewed with the ``list countries'' request. Note that not all devices support changing the country code from a default @@ -1063,7 +1070,7 @@ DFS embodies several facilities including detection of overlapping radar signals, dynamic transmit power control, and channel selection according to a least-congested criteria. DFS support is mandatory for some 5GHz frequencies in certain -locales (e.g. ETSI). +locales (e.g., ETSI). By default DFS is enabled according to the regulatory definitions specified in /etc/regdomain.xml and the current country code, regdomain, and channel. @@ -1115,7 +1122,7 @@ specifies the number of beacon intervals between DTIM and must be in the range 1 to 15. By default DTIM is 1 (i.e., DTIM occurs at each beacon). .It Cm quiet -Enable the use of quiet IE. Hostap will use this to silent other +Enable the use of quiet IE. Hostap will use this to silence other stations to reduce interference for radar detection when operating on 5GHz frequency and doth support is enabled. Use @@ -1168,7 +1175,7 @@ Enable Dynamic WDS (DWDS) support. DWDS is a facility by which 4-address traffic can be carried between stations operating in infrastructure mode. A station first associates to an access point and authenticates using -normal procedures (e.g. WPA). +normal procedures (e.g., WPA). Then 4-address frames are passed to carry traffic for stations operating on either side of the wireless link. DWDS extends the normal WDS mechanism by leveraging existing security @@ -1186,7 +1193,7 @@ When DWDS is enabled on a station, traffic with a destination address different from the peer station are encapsulated in a 4-address frame and transmitted to the peer. All 4-address traffic uses the security information of the stations -(e.g. cryptographic keys). +(e.g., cryptographic keys). A station is associated using 802.11n facilities may transport 4-address traffic using these same mechanisms; this depends on available resources and capabilities of the device. @@ -1236,7 +1243,7 @@ Stations negotiate use of these facilities, termed HT20 and HT40, when they associate. To disable all use of 802.11n use .Fl ht . -To disable use of HT20 (e.g. to force only HT40 use) use +To disable use of HT20 (e.g., to force only HT40 use) use .Fl ht20 . To disable use of HT40 use .Fl ht40 . @@ -1250,7 +1257,7 @@ Auto Channel Selection is used to locate a channel to operate on, HT configuration controls whether legacy, HT20, or HT40 operation is setup on the selected channel. If a fixed channel is specified for a station then HT configuration can -be given as part of the channel specification; e.g. 6:ht/20 to setup +be given as part of the channel specification; e.g., 6:ht/20 to setup HT20 operation on channel 6. .It Cm htcompat Enable use of compatibility support for pre-802.11n devices (default). @@ -1506,13 +1513,13 @@ The default setting is 6 but drivers may override this with a value they choose. .It Cm mcastrate Ar rate Set the rate for transmitting multicast/broadcast frames. -Rates are specified as megabits/second in decimal; e.g.\& 5.5 for 5.5 Mb/s. +Rates are specified as megabits/second in decimal; e.g.,\& 5.5 for 5.5 Mb/s. This rate should be valid for the current operating conditions; if an invalid rate is specified drivers are free to chose an appropriate rate. .It Cm mgtrate Ar rate Set the rate for transmitting management and/or control frames. -Rates are specified as megabits/second in decimal; e.g.\& 5.5 for 5.5 Mb/s. +Rates are specified as megabits/second in decimal; e.g.,\& 5.5 for 5.5 Mb/s. .It Cm outdoor Set the location to use in calculating regulatory constraints. The location is also advertised in beacon and probe response frames @@ -1672,7 +1679,7 @@ request can be used to show recent scan results without initiating a new scan. .It Cm scanvalid Ar threshold Set the maximum time the scan cache contents are considered valid; -i.e. will be used without first triggering a scan operation to +i.e., will be used without first triggering a scan operation to refresh the data. The .Ar threshold @@ -1734,7 +1741,7 @@ When operating with TDMA, setup a BSS with slots. The slot count may be at most 8. The current implementation is only tested with two stations -(i.e. point to point applications). +(i.e., point to point applications). This setting is only meaningful when a station is configured as slot 0; other stations adopt this setting from the BSS they join. By default @@ -1758,7 +1765,7 @@ is set to 10 milliseconds. When operating with TDMA, setup a BSS such that beacons are transmitted every .Ar intval superframes to synchronize the TDMA slot timing. -A superframe is defined as the number of slots times the slot length; e.g. +A superframe is defined as the number of slots times the slot length; e.g., a BSS with two slots of 10 milliseconds has a 20 millisecond superframe. The beacon interval may not be zero. A lower setting of @@ -1784,7 +1791,7 @@ the driver will use the setting closest to the specified value. Not all adapters support changing the transmit power. .It Cm ucastrate Ar rate Set a fixed rate for transmitting unicast frames. -Rates are specified as megabits/second in decimal; e.g.\& 5.5 for 5.5 Mb/s. +Rates are specified as megabits/second in decimal; e.g.,\& 5.5 for 5.5 Mb/s. This rate should be valid for the current operating conditions; if an invalid rate is specified drivers are free to chose an appropriate rate. @@ -2519,7 +2526,7 @@ protocol on an interface: Set the virtual host ID. This is a required setting to initiate .Xr carp 4 . -If the virtual host ID doesn't exist yet, it is created and attached to the +If the virtual host ID does not exist yet, it is created and attached to the interface, otherwise configuration of an existing vhid is adjusted. If the .Cm vhid @@ -2628,9 +2635,6 @@ The flag disables this behavior. .Pp Only the super-user may modify the configuration of a network interface. -.Sh NOTES -The media selection system is relatively new and only some drivers support -it (or have need for it). .Sh EXAMPLES Assign the IPv4 address .Li 192.0.2.10 , @@ -2714,7 +2718,9 @@ tried to alter an interface's configuration. .Xr pfsync 4 , .Xr polling 4 , .Xr vlan 4 , +.Xr devd.conf 5 , .\" .Xr eon 5 , +.Xr devd 8 , .Xr rc 8 , .Xr routed 8 , .Xr jail 8 , diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c index 870acdd0445c..983e21fc0401 100644 --- a/sbin/ifconfig/ifconfig.c +++ b/sbin/ifconfig/ifconfig.c @@ -520,7 +520,7 @@ top: AF_LOCAL : afp->af_af; if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0 && - (uafp != NULL || errno != EPROTONOSUPPORT || + (uafp != NULL || errno != EAFNOSUPPORT || (s = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0)) err(1, "socket(family %u,SOCK_DGRAM", ifr.ifr_addr.sa_family); diff --git a/sbin/ifconfig/ifieee80211.c b/sbin/ifconfig/ifieee80211.c index c2b767894a13..d0b4917d3b04 100644 --- a/sbin/ifconfig/ifieee80211.c +++ b/sbin/ifconfig/ifieee80211.c @@ -4025,7 +4025,9 @@ list_mesh(int s) (rt->imr_flags & IEEE80211_MESHRT_FLAGS_VALID) ? 'V' : '!', (rt->imr_flags & IEEE80211_MESHRT_FLAGS_PROXY) ? - 'P' : ' '); + 'P' : + (rt->imr_flags & IEEE80211_MESHRT_FLAGS_GATE) ? + 'G' :' '); } } diff --git a/sbin/mdconfig/mdconfig.8 b/sbin/mdconfig/mdconfig.8 index 89f150e8d1a4..c18027cabb94 100644 --- a/sbin/mdconfig/mdconfig.8 +++ b/sbin/mdconfig/mdconfig.8 @@ -41,7 +41,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 27, 2012 +.Dd November 3, 2012 .Dt MDCONFIG 8 .Os .Sh NAME @@ -267,6 +267,18 @@ are implied device, and then mount the new memory disk: .Bd -literal -offset indent mount -t cd9660 /dev/`mdconfig -f cdimage.iso` /mnt +.Pp +.Ed +Create a file-backed device from a hard disk image that begins +with 512K of raw header information. +.Xr gnop 8 +is used to skip over the header information, positioning +.Pa md1.nop +to the start of the filesystem in the image. +.Bd -literal -offset indent +mdconfig -f diskimage.img -u 1 +gnop create -o 512K md1 +mount /dev/md1.nop /mnt .Ed .Sh SEE ALSO .Xr md 4 , diff --git a/sbin/mdconfig/mdconfig.c b/sbin/mdconfig/mdconfig.c index 55d1567ca970..70cefe916d19 100644 --- a/sbin/mdconfig/mdconfig.c +++ b/sbin/mdconfig/mdconfig.c @@ -84,7 +84,7 @@ usage(void) " mdconfig -r -u unit -s size [-o [no]force]\n" " mdconfig -l [-v] [-n] [-u unit]\n" " mdconfig file\n"); - fprintf(stderr, "\t\ttype = {malloc, preload, vnode, swap}\n"); + fprintf(stderr, "\t\ttype = {malloc, vnode, swap}\n"); fprintf(stderr, "\t\toption = {cluster, compress, reserve}\n"); fprintf(stderr, "\t\tsize = %%d (512 byte blocks), %%db (B),\n"); fprintf(stderr, "\t\t %%dk (kB), %%dm (MB), %%dg (GB) or\n"); @@ -148,8 +148,6 @@ main(int argc, char **argv) if (!strcmp(optarg, "malloc")) { mdio.md_type = MD_MALLOC; mdio.md_options |= MD_AUTOUNIT | MD_COMPRESS; - } else if (!strcmp(optarg, "preload")) { - mdio.md_type = MD_PRELOAD; } else if (!strcmp(optarg, "vnode")) { mdio.md_type = MD_VNODE; mdio.md_options |= MD_CLUSTER | MD_AUTOUNIT | MD_COMPRESS; diff --git a/sbin/mount_nfs/mount_nfs.8 b/sbin/mount_nfs/mount_nfs.8 index b1b5c6e21cfc..26ed091b0638 100644 --- a/sbin/mount_nfs/mount_nfs.8 +++ b/sbin/mount_nfs/mount_nfs.8 @@ -28,7 +28,7 @@ .\" @(#)mount_nfs.8 8.3 (Berkeley) 3/29/95 .\" $FreeBSD$ .\" -.Dd May 3, 2011 +.Dd December 9, 2012 .Dt MOUNT_NFS 8 .Os .Sh NAME @@ -175,6 +175,18 @@ Use the NFS Version 3 protocol. Use the NFS Version 4 protocol. This option will force the mount to use TCP transport. +.It Cm minorversion Ns = Ns Aq Ar value +Override the default of 0 for the minor version of the NFS Version 4 protocol. +The only minor version currently supported is 1. +This option is only meaningful when used with the +.Cm nfsv4 +option. +.It Cm pnfs +Enable support for parallel NFS (pNFS) for minor version 1 of the +NFS Version 4 protocol. +This option is only meaningful when used with the +.Cm minorversion +option. .It Cm noconn For UDP mount points, do not do a .Xr connect 2 . diff --git a/sbin/mount_nullfs/mount_nullfs.c b/sbin/mount_nullfs/mount_nullfs.c index c88db3d91cb5..aaf66e527ea3 100644 --- a/sbin/mount_nullfs/mount_nullfs.c +++ b/sbin/mount_nullfs/mount_nullfs.c @@ -57,27 +57,35 @@ static const char rcsid[] = #include "mntopts.h" -static struct mntopt mopts[] = { - MOPT_STDOPTS, - MOPT_END -}; - int subdir(const char *, const char *); static void usage(void) __dead2; int main(int argc, char *argv[]) { - struct iovec iov[6]; - int ch, mntflags; + struct iovec *iov; + char *p, *val; char source[MAXPATHLEN]; char target[MAXPATHLEN]; + char errmsg[255]; + int ch, mntflags, iovlen; + char nullfs[] = "nullfs"; + iov = NULL; + iovlen = 0; mntflags = 0; + errmsg[0] = '\0'; while ((ch = getopt(argc, argv, "o:")) != -1) switch(ch) { case 'o': - getmntopts(optarg, mopts, &mntflags, 0); + val = strdup(""); + p = strchr(optarg, '='); + if (p != NULL) { + free(val); + *p = '\0'; + val = p + 1; + } + build_iovec(&iov, &iovlen, optarg, val, (size_t)-1); break; case '?': default: @@ -99,21 +107,16 @@ main(int argc, char *argv[]) errx(EX_USAGE, "%s (%s) and %s are not distinct paths", argv[0], target, argv[1]); - iov[0].iov_base = strdup("fstype"); - iov[0].iov_len = sizeof("fstype"); - iov[1].iov_base = strdup("nullfs"); - iov[1].iov_len = strlen(iov[1].iov_base) + 1; - iov[2].iov_base = strdup("fspath"); - iov[2].iov_len = sizeof("fspath"); - iov[3].iov_base = source; - iov[3].iov_len = strlen(source) + 1; - iov[4].iov_base = strdup("target"); - iov[4].iov_len = sizeof("target"); - iov[5].iov_base = target; - iov[5].iov_len = strlen(target) + 1; - - if (nmount(iov, 6, mntflags)) - err(1, NULL); + build_iovec(&iov, &iovlen, "fstype", nullfs, (size_t)-1); + build_iovec(&iov, &iovlen, "fspath", source, (size_t)-1); + build_iovec(&iov, &iovlen, "target", target, (size_t)-1); + build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg)); + if (nmount(iov, iovlen, mntflags) < 0) { + if (errmsg[0] != 0) + err(1, "%s: %s", source, errmsg); + else + err(1, "%s", source); + } exit(0); } diff --git a/sbin/newfs_msdos/newfs_msdos.c b/sbin/newfs_msdos/newfs_msdos.c index c2e9a354ccd8..fe1631a73ca9 100644 --- a/sbin/newfs_msdos/newfs_msdos.c +++ b/sbin/newfs_msdos/newfs_msdos.c @@ -808,7 +808,7 @@ getdiskinfo(int fd, const char *fname, const char *dtype, __unused int oflag, struct stat st; if (fstat(fd, &st)) - err(1, "Cannot get disk size"); + err(1, "cannot get disk size"); /* create a fake geometry for a file image */ ms = st.st_size; dlp.d_secsize = 512; @@ -832,18 +832,18 @@ getdiskinfo(int fd, const char *fname, const char *dtype, __unused int oflag, if (ioctl(fd, DIOCGDINFO, &dlp) == -1) { if (bpb->bpbBytesPerSec == 0 && ioctl(fd, DIOCGSECTORSIZE, &dlp.d_secsize) == -1) - errx(1, "Cannot get sector size, %s", strerror(errno)); + err(1, "cannot get sector size"); dlp.d_secperunit = ms / dlp.d_secsize; if (bpb->bpbSecPerTrack == 0 && ioctl(fd, DIOCGFWSECTORS, &dlp.d_nsectors) == -1) { - warnx("Cannot get number of sectors per track, %s", strerror(errno)); + warn("cannot get number of sectors per track"); dlp.d_nsectors = 63; } if (bpb->bpbHeads == 0 && ioctl(fd, DIOCGFWHEADS, &dlp.d_ntracks) == -1) { - warnx("Cannot get number of heads, %s", strerror(errno)); + warn("cannot get number of heads"); if (dlp.d_secperunit <= 63*1*1024) dlp.d_ntracks = 1; else if (dlp.d_secperunit <= 63*16*1024) diff --git a/sbin/pflogd/Makefile b/sbin/pflogd/Makefile index ea37bd1791bf..fcff8eb45135 100644 --- a/sbin/pflogd/Makefile +++ b/sbin/pflogd/Makefile @@ -9,7 +9,7 @@ MAN= pflogd.8 CFLAGS+=-include ${.CURDIR}/../../lib/libpcap/config.h LDADD= -lpcap -DPADD= ${LIBPCAP} ${LIBUTIL} +DPADD= ${LIBPCAP} WARNS?= 2 diff --git a/sbin/recoverdisk/recoverdisk.c b/sbin/recoverdisk/recoverdisk.c index 3a92d1db0a85..caa8ebdeccbe 100644 --- a/sbin/recoverdisk/recoverdisk.c +++ b/sbin/recoverdisk/recoverdisk.c @@ -156,6 +156,7 @@ main(int argc, char * const argv[]) int error, state; u_char *buf; u_int sectorsize; + u_int stripesize; time_t t1, t2; struct stat sb; u_int n, snapshot = 60; @@ -201,6 +202,10 @@ main(int argc, char * const argv[]) if (error < 0) err(1, "DIOCGSECTORSIZE failed"); + error = ioctl(fdr, DIOCGSTRIPESIZE, &stripesize); + if (error == 0 && stripesize > sectorsize) + sectorsize = stripesize; + minsize = sectorsize; bigsize = (bigsize / sectorsize) * sectorsize; diff --git a/sbin/route/keywords b/sbin/route/keywords index 8817f3055b80..adfba7cf111b 100644 --- a/sbin/route/keywords +++ b/sbin/route/keywords @@ -10,6 +10,7 @@ del delete dst expire +fib flush gateway genmask diff --git a/sbin/route/route.8 b/sbin/route/route.8 index 6bf65b4ac55f..b7861068bacb 100644 --- a/sbin/route/route.8 +++ b/sbin/route/route.8 @@ -28,7 +28,7 @@ .\" @(#)route.8 8.3 (Berkeley) 3/19/94 .\" $FreeBSD$ .\" -.Dd March 24, 2012 +.Dd November 17, 2012 .Dt ROUTE 8 .Os .Sh NAME @@ -118,16 +118,14 @@ The monitor command has the syntax: .Bd -ragged -offset indent -compact .Nm .Op Fl n -.Cm monitor +.Cm monitor Op Fl fib Ar number .Ed .Pp The flush command has the syntax: .Pp .Bd -ragged -offset indent -compact .Nm -.Op Fl n -.Cm flush -.Op Ar family +.Oo Fl n Cm flush Oc Oo Ar family Oc Op Fl fib Ar number .Ed .Pp If the @@ -144,6 +142,11 @@ or .Fl inet modifiers, only routes having destinations with addresses in the delineated family will be deleted. +When a +.Fl fib +option is specified, the operation will be applied to +the specified FIB +.Pq routing table . .Pp The other commands have the following syntax: .Pp @@ -154,6 +157,7 @@ The other commands have the following syntax: .Op Fl net No \&| Fl host .Ar destination gateway .Op Ar netmask +.Op Fl fib Ar number .Ed .Pp where @@ -210,9 +214,15 @@ A .Ar destination of .Ar default -is a synonym for -.Fl net Li 0.0.0.0 , -which is the default route. +is a synonym for the default route. +For +.Li IPv4 +it is +.Fl net Fl inet Li 0.0.0.0 , +and for +.Li IPv6 +it is +.Fl net Fl inet6 Li :: . .Pp If the destination is directly reachable via an interface requiring @@ -314,6 +324,33 @@ specify that all ensuing metrics may be locked by the .Fl lockrest meta-modifier. .Pp +The optional modifier +.Fl fib Ar number +specifies that the command will be applied to a non-default FIB. +The +.Ar number +must be smaller than the +.Va net.fibs +.Xr sysctl 8 +MIB. +When this modifier is not specified, +or a negative number is specified, +the default FIB shown in the +.Va net.my_fibnum +.Xr sysctl 8 +MIB will be used. +.Pp +The +.Ar number +allows multiple FIBs by a comma-separeted list and/or range +specification. +The +.Qq Fl fib Li 2,4,6 +means the FIB number 2, 4, and 6. +The +.Qq Fl fib Li 1,3-5,6 +means the 1, 3, 4, 5, and 6. +.Pp In a .Cm change or diff --git a/sbin/route/route.c b/sbin/route/route.c index 717a09ad2a8b..48f90a768d23 100644 --- a/sbin/route/route.c +++ b/sbin/route/route.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include <sys/ioctl.h> #include <sys/sysctl.h> #include <sys/types.h> +#include <sys/queue.h> #include <net/if.h> #include <net/route.h> @@ -77,7 +78,6 @@ struct keytab { {0, 0} }; -struct ortentry route; union sockunion { struct sockaddr sa; struct sockaddr_in sin; @@ -86,7 +86,6 @@ union sockunion { #endif struct sockaddr_at sat; struct sockaddr_dl sdl; - struct sockaddr_inarp sinarp; struct sockaddr_storage ss; /* added to avoid memory overrun */ } so_dst, so_gate, so_mask, so_genmask, so_ifa, so_ifp; @@ -94,17 +93,20 @@ typedef union sockunion *sup; int pid, rtm_addrs; int s; int forcehost, forcenet, doflush, nflag, af, qflag, tflag; -int iflag, verbose, aflen = sizeof (struct sockaddr_in); +int verbose, aflen = sizeof (struct sockaddr_in); int locking, lockrest, debugonly; struct rt_metrics rt_metrics; u_long rtm_inits; uid_t uid; +static int defaultfib; +static int numfibs; static int atalk_aton(const char *, struct at_addr *); static char *atalk_ntoa(struct at_addr); static void bprintf(FILE *, int, u_char *); static void flushroutes(int argc, char *argv[]); -static int getaddr(int, char *, struct hostent **); +static int flushroutes_fib(int); +static int getaddr(int, char *, struct hostent **, int); static int keyword(const char *); static void inet_makenetandmask(u_long, struct sockaddr_in *, u_long); #ifdef INET6 @@ -112,21 +114,36 @@ static int inet6_makenetandmask(struct sockaddr_in6 *, const char *); #endif static void interfaces(void); static void mask_addr(void); -static void monitor(void); +static void monitor(int, char*[]); static const char *netname(struct sockaddr *); static void newroute(int, char **); +static int newroute_fib(int, char *, int); static void pmsg_addrs(char *, int, size_t); static void pmsg_common(struct rt_msghdr *, size_t); static int prefixlen(const char *); -static void print_getmsg(struct rt_msghdr *, int); +static void print_getmsg(struct rt_msghdr *, int, int); static void print_rtmsg(struct rt_msghdr *, size_t); static const char *routename(struct sockaddr *); -static int rtmsg(int, int); +static int rtmsg(int, int, int); static void set_metric(char *, int); +static int set_sofib(int); +static int set_procfib(int); static void sockaddr(char *, struct sockaddr *); static void sodump(sup, const char *); extern char *iso_ntoa(void); +struct fibl { + TAILQ_ENTRY(fibl) fl_next; + + int fl_num; + int fl_error; + int fl_errno; +}; +TAILQ_HEAD(fibl_head_t, fibl) fibl_head; + +static int fiboptlist_csv(const char *, struct fibl_head_t *); +static int fiboptlist_range(const char *, struct fibl_head_t *); + static void usage(const char *) __dead2; void @@ -144,6 +161,7 @@ int main(int argc, char **argv) { int ch; + size_t len; if (argc < 2) usage(NULL); @@ -180,6 +198,17 @@ main(int argc, char **argv) s = socket(PF_ROUTE, SOCK_RAW, 0); if (s < 0) err(EX_OSERR, "socket"); + + len = sizeof(numfibs); + if (sysctlbyname("net.fibs", (void *)&numfibs, &len, NULL, 0) == -1) + numfibs = -1; + + len = sizeof(defaultfib); + if (numfibs != -1 && + sysctlbyname("net.my_fibnum", (void *)&defaultfib, &len, NULL, + 0) == -1) + defaultfib = -1; + if (*argv != NULL) switch (keyword(*argv)) { case K_GET: @@ -195,7 +224,7 @@ main(int argc, char **argv) /* NOTREACHED */ case K_MONITOR: - monitor(); + monitor(argc, argv); /* NOTREACHED */ case K_FLUSH: @@ -207,6 +236,136 @@ main(int argc, char **argv) /* NOTREACHED */ } +static int +set_sofib(int fib) +{ + + if (fib < 0) + return (0); + return (setsockopt(s, SOL_SOCKET, SO_SETFIB, (void *)&fib, + sizeof(fib))); +} + +static int +set_procfib(int fib) +{ + + if (fib < 0) + return (0); + return (setfib(fib)); +} + +static int +fiboptlist_range(const char *arg, struct fibl_head_t *flh) +{ + struct fibl *fl; + char *str0, *str, *token, *endptr; + int fib[2], i, error; + + str0 = str = strdup(arg); + error = 0; + i = 0; + while ((token = strsep(&str, "-")) != NULL) { + switch (i) { + case 0: + case 1: + errno = 0; + fib[i] = strtol(token, &endptr, 0); + if (errno == 0) { + if (*endptr != '\0' || + fib[i] < 0 || + (numfibs != -1 && fib[i] > numfibs - 1)) + errno = EINVAL; + } + if (errno) + error = 1; + break; + default: + error = 1; + } + if (error) + goto fiboptlist_range_ret; + i++; + } + if (fib[0] >= fib[1]) { + error = 1; + goto fiboptlist_range_ret; + } + for (i = fib[0]; i <= fib[1]; i++) { + fl = calloc(1, sizeof(*fl)); + if (fl == NULL) { + error = 1; + goto fiboptlist_range_ret; + } + fl->fl_num = i; + TAILQ_INSERT_TAIL(flh, fl, fl_next); + } +fiboptlist_range_ret: + free(str0); + return (error); +} + +#define ALLSTRLEN 64 +static int +fiboptlist_csv(const char *arg, struct fibl_head_t *flh) +{ + struct fibl *fl; + char *str0, *str, *token, *endptr; + int fib, error; + + if (strcmp("all", arg) == 0) { + str = calloc(1, ALLSTRLEN); + if (str == NULL) { + error = 1; + goto fiboptlist_csv_ret; + } + if (numfibs > 1) + snprintf(str, ALLSTRLEN - 1, "%d-%d", 0, numfibs - 1); + else + snprintf(str, ALLSTRLEN - 1, "%d", 0); + } else if (strcmp("default", arg) == 0) { + str0 = str = calloc(1, ALLSTRLEN); + if (str == NULL) { + error = 1; + goto fiboptlist_csv_ret; + } + snprintf(str, ALLSTRLEN - 1, "%d", defaultfib); + } else + str0 = str = strdup(arg); + + error = 0; + while ((token = strsep(&str, ",")) != NULL) { + if (*token != '-' && strchr(token, '-') != NULL) { + error = fiboptlist_range(token, flh); + if (error) + goto fiboptlist_csv_ret; + } else { + errno = 0; + fib = strtol(token, &endptr, 0); + if (errno == 0) { + if (*endptr != '\0' || + fib < 0 || + (numfibs != -1 && fib > numfibs - 1)) + errno = EINVAL; + } + if (errno) { + error = 1; + goto fiboptlist_csv_ret; + } + fl = calloc(1, sizeof(*fl)); + if (fl == NULL) { + error = 1; + goto fiboptlist_csv_ret; + } + fl->fl_num = fib; + TAILQ_INSERT_TAIL(flh, fl, fl_next); + } + } +fiboptlist_csv_ret: + free(str0); + return (error); +} + /* * Purge all entries in the routing tables not * associated with network interfaces. @@ -214,38 +373,71 @@ main(int argc, char **argv) static void flushroutes(int argc, char *argv[]) { - size_t needed; - int mib[6], rlen, seqno, count = 0; - char *buf, *next, *lim; - struct rt_msghdr *rtm; + struct fibl *fl; + int error; - if (uid != 0 && !debugonly) { + if (uid != 0 && !debugonly && !tflag) { errx(EX_NOPERM, "must be root to alter routing table"); } shutdown(s, SHUT_RD); /* Don't want to read back our messages */ - if (argc > 1) { + + TAILQ_INIT(&fibl_head); + while (argc > 1) { + argc--; argv++; - if (argc == 2 && **argv == '-') - switch (keyword(*argv + 1)) { - case K_INET: - af = AF_INET; - break; + if (**argv != '-') + usage(*argv); + switch (keyword(*argv + 1)) { + case K_INET: + af = AF_INET; + break; #ifdef INET6 - case K_INET6: - af = AF_INET6; - break; + case K_INET6: + af = AF_INET6; + break; #endif - case K_ATALK: - af = AF_APPLETALK; - break; - case K_LINK: - af = AF_LINK; - break; - default: - goto bad; - } else -bad: usage(*argv); + case K_ATALK: + af = AF_APPLETALK; + break; + case K_LINK: + af = AF_LINK; + break; + case K_FIB: + if (!--argc) + usage(*argv); + error = fiboptlist_csv(*++argv, &fibl_head); + if (error) + errx(EX_USAGE, "invalid fib number: %s", *argv); + break; + default: + usage(*argv); + } } + if (TAILQ_EMPTY(&fibl_head)) { + error = fiboptlist_csv("default", &fibl_head); + if (error) + errx(EX_OSERR, "fiboptlist_csv failed."); + } + TAILQ_FOREACH(fl, &fibl_head, fl_next) + flushroutes_fib(fl->fl_num); +} + +static int +flushroutes_fib(int fib) +{ + struct rt_msghdr *rtm; + size_t needed; + char *buf, *next, *lim; + int mib[6], rlen, seqno, count = 0; + int error; + + error = set_sofib(fib); + error += set_procfib(fib); + if (error) { + warn("fib number %d is ignored", fib); + return (error); + } + retry: mib[0] = CTL_NET; mib[1] = PF_ROUTE; @@ -303,13 +495,17 @@ retry: print_rtmsg(rtm, rlen); else { struct sockaddr *sa = (struct sockaddr *)(rtm + 1); - (void) printf("%-20.20s ", rtm->rtm_flags & RTF_HOST ? + + printf("%-20.20s ", rtm->rtm_flags & RTF_HOST ? routename(sa) : netname(sa)); sa = (struct sockaddr *)(SA_SIZE(sa) + (char *)sa); - (void) printf("%-20.20s ", routename(sa)); - (void) printf("done\n"); + printf("%-20.20s ", routename(sa)); + if (fib >= 0) + printf("-fib %-3d ", fib); + printf("done\n"); } } + return (error); } const char * @@ -372,18 +568,6 @@ routename(struct sockaddr *sa) memcpy(&sin6, sa, sa->sa_len); sin6.sin6_len = sizeof(struct sockaddr_in6); sin6.sin6_family = AF_INET6; -#ifdef __KAME__ - if (sa->sa_len == sizeof(struct sockaddr_in6) && - (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) || - IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr) || - IN6_IS_ADDR_MC_NODELOCAL(&sin6.sin6_addr)) && - sin6.sin6_scope_id == 0) { - sin6.sin6_scope_id = - ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]); - sin6.sin6_addr.s6_addr[2] = 0; - sin6.sin6_addr.s6_addr[3] = 0; - } -#endif if (nflag) niflags |= NI_NUMERICHOST; if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, @@ -422,7 +606,7 @@ routename(struct sockaddr *sa) /* * Return the name of the network whose address is given. - * The address is assumed to be that of a net or subnet, not a host. + * The address is assumed to be that of a net, not a host. */ const char * netname(struct sockaddr *sa) @@ -430,9 +614,8 @@ netname(struct sockaddr *sa) const char *cp = NULL; static char line[MAXHOSTNAMELEN + 1]; struct netent *np = NULL; - u_long net, mask; u_long i; - int n, subnetshift; + int n; switch (sa->sa_family) { @@ -444,28 +627,7 @@ netname(struct sockaddr *sa) if (in.s_addr == 0) cp = "default"; else if (!nflag) { - if (IN_CLASSA(i)) { - mask = IN_CLASSA_NET; - subnetshift = 8; - } else if (IN_CLASSB(i)) { - mask = IN_CLASSB_NET; - subnetshift = 8; - } else { - mask = IN_CLASSC_NET; - subnetshift = 4; - } - /* - * If there are more bits than the standard mask - * would suggest, subnets must be in use. - * Guess at the subnet mask, assuming reasonable - * width subnet fields. - */ - while (in.s_addr & ~mask) - mask |= mask >> subnetshift; - net = in.s_addr & mask; - while ((mask & 1) == 0) - mask >>= 1, net >>= 1; - np = getnetbyaddr(net, AF_INET); + np = getnetbyaddr(i, AF_INET); if (np != NULL) cp = np->n_name; } @@ -498,18 +660,6 @@ netname(struct sockaddr *sa) memcpy(&sin6, sa, sa->sa_len); sin6.sin6_len = sizeof(struct sockaddr_in6); sin6.sin6_family = AF_INET6; -#ifdef __KAME__ - if (sa->sa_len == sizeof(struct sockaddr_in6) && - (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) || - IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr) || - IN6_IS_ADDR_MC_NODELOCAL(&sin6.sin6_addr)) && - sin6.sin6_scope_id == 0) { - sin6.sin6_scope_id = - ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]); - sin6.sin6_addr.s6_addr[2] = 0; - sin6.sin6_addr.s6_addr[3] = 0; - } -#endif if (nflag) niflags |= NI_NUMERICHOST; if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, @@ -573,18 +723,32 @@ set_metric(char *value, int key) *valp = atoi(value); } +#define F_ISHOST 0x01 +#define F_FORCENET 0x02 +#define F_FORCEHOST 0x04 +#define F_PROXY 0x08 +#define F_INTERFACE 0x10 + static void newroute(int argc, char **argv) { + struct hostent *hp; + struct fibl *fl; char *cmd; - const char *dest = "", *gateway = "", *errmsg; - int ishost = 0, proxy = 0, ret, attempts, oerrno, flags = RTF_STATIC; - int key; - struct hostent *hp = 0; + const char *dest, *gateway, *errmsg; + int key, error, flags, nrflags, fibnum; - if (uid != 0) { + if (uid != 0 && !debugonly && !tflag) { errx(EX_NOPERM, "must be root to alter routing table"); } + + dest = NULL; + gateway = NULL; + flags = RTF_STATIC; + nrflags = 0; + hp = NULL; + TAILQ_INIT(&fibl_head); + cmd = argv[0]; if (*cmd != 'g' && *cmd != 's') shutdown(s, SHUT_RD); /* Don't want to read back our messages */ @@ -616,7 +780,7 @@ newroute(int argc, char **argv) break; case K_IFACE: case K_INTERFACE: - iflag++; + nrflags |= F_INTERFACE; break; case K_NOSTATIC: flags &= ~RTF_STATIC; @@ -628,7 +792,7 @@ newroute(int argc, char **argv) lockrest = 1; break; case K_HOST: - forcehost++; + nrflags |= F_FORCEHOST; break; case K_REJECT: flags |= RTF_REJECT; @@ -643,7 +807,7 @@ newroute(int argc, char **argv) flags |= RTF_PROTO2; break; case K_PROXY: - proxy = 1; + nrflags |= F_PROXY; break; case K_XRESOLVE: flags |= RTF_XRESOLVE; @@ -657,49 +821,58 @@ newroute(int argc, char **argv) case K_NOSTICK: flags &= ~RTF_STICKY; break; + case K_FIB: + if (!--argc) + usage(NULL); + error = fiboptlist_csv(*++argv, &fibl_head); + if (error) + errx(EX_USAGE, + "invalid fib number: %s", *argv); + break; case K_IFA: if (!--argc) usage(NULL); - (void) getaddr(RTA_IFA, *++argv, 0); + getaddr(RTA_IFA, *++argv, 0, nrflags); break; case K_IFP: if (!--argc) usage(NULL); - (void) getaddr(RTA_IFP, *++argv, 0); + getaddr(RTA_IFP, *++argv, 0, nrflags); break; case K_GENMASK: if (!--argc) usage(NULL); - (void) getaddr(RTA_GENMASK, *++argv, 0); + getaddr(RTA_GENMASK, *++argv, 0, nrflags); break; case K_GATEWAY: if (!--argc) usage(NULL); - (void) getaddr(RTA_GATEWAY, *++argv, 0); + getaddr(RTA_GATEWAY, *++argv, 0, nrflags); break; case K_DST: if (!--argc) usage(NULL); - ishost = getaddr(RTA_DST, *++argv, &hp); + if (getaddr(RTA_DST, *++argv, &hp, nrflags)) + nrflags |= F_ISHOST; dest = *argv; break; case K_NETMASK: if (!--argc) usage(NULL); - (void) getaddr(RTA_NETMASK, *++argv, 0); + getaddr(RTA_NETMASK, *++argv, 0, nrflags); /* FALLTHROUGH */ case K_NET: - forcenet++; + nrflags |= F_FORCENET; break; case K_PREFIXLEN: if (!--argc) usage(NULL); if (prefixlen(*++argv) == -1) { - forcenet = 0; - ishost = 1; + nrflags &= ~F_FORCENET; + nrflags |= F_ISHOST; } else { - forcenet = 1; - ishost = 0; + nrflags |= F_FORCENET; + nrflags &= ~F_ISHOST; } break; case K_MTU: @@ -721,18 +894,20 @@ newroute(int argc, char **argv) } else { if ((rtm_addrs & RTA_DST) == 0) { dest = *argv; - ishost = getaddr(RTA_DST, *argv, &hp); + if (getaddr(RTA_DST, *argv, &hp, nrflags)) + nrflags |= F_ISHOST; } else if ((rtm_addrs & RTA_GATEWAY) == 0) { gateway = *argv; - (void) getaddr(RTA_GATEWAY, *argv, &hp); + getaddr(RTA_GATEWAY, *argv, &hp, nrflags); } else { - (void) getaddr(RTA_NETMASK, *argv, 0); - forcenet = 1; + getaddr(RTA_NETMASK, *argv, 0, nrflags); + nrflags |= F_FORCENET; } } } - if (forcehost) { - ishost = 1; + + if (nrflags & F_FORCEHOST) { + nrflags |= F_ISHOST; #ifdef INET6 if (af == AF_INET6) { rtm_addrs &= ~RTA_NETMASK; @@ -740,100 +915,148 @@ newroute(int argc, char **argv) } #endif } - if (forcenet) - ishost = 0; + if (nrflags & F_FORCENET) + nrflags &= ~F_ISHOST; flags |= RTF_UP; - if (ishost) + if (nrflags & F_ISHOST) flags |= RTF_HOST; - if (iflag == 0) + if ((nrflags & F_INTERFACE) == 0) flags |= RTF_GATEWAY; - if (proxy) { - so_dst.sinarp.sin_other = SIN_PROXY; + if (nrflags & F_PROXY) flags |= RTF_ANNOUNCE; + if (dest == NULL) + dest = ""; + if (gateway == NULL) + gateway = ""; + + if (TAILQ_EMPTY(&fibl_head)) { + error = fiboptlist_csv("default", &fibl_head); + if (error) + errx(EX_OSERR, "fiboptlist_csv failed."); } - for (attempts = 1; ; attempts++) { - errno = 0; - if ((ret = rtmsg(*cmd, flags)) == 0) - break; - if (errno != ENETUNREACH && errno != ESRCH) - break; - if (af == AF_INET && *gateway != '\0' && - hp != NULL && hp->h_addr_list[1] != NULL) { - hp->h_addr_list++; - memmove(&so_gate.sin.sin_addr, hp->h_addr_list[0], - MIN((size_t)hp->h_length, - sizeof(so_gate.sin.sin_addr))); - } else - break; + error = 0; + TAILQ_FOREACH(fl, &fibl_head, fl_next) { + fl->fl_error = newroute_fib(fl->fl_num, cmd, flags); + if (fl->fl_error) + fl->fl_errno = errno; + error += fl->fl_error; } if (*cmd == 'g' || *cmd == 's') - exit(ret != 0); + exit(error); + + error = 0; if (!qflag) { - oerrno = errno; - (void) printf("%s %s %s", cmd, ishost? "host" : "net", dest); - if (*gateway) { - (void) printf(": gateway %s", gateway); - if (attempts > 1 && ret == 0 && af == AF_INET) - (void) printf(" (%s)", - inet_ntoa(((struct sockaddr_in *)&route.rt_gateway)->sin_addr)); + fibnum = 0; + TAILQ_FOREACH(fl, &fibl_head, fl_next) { + if (fl->fl_error == 0) + fibnum++; } - if (ret == 0) { - (void) printf("\n"); - } else { - switch (oerrno) { - case ESRCH: - errmsg = "not in table"; - break; - case EBUSY: - errmsg = "entry in use"; - break; - case ENOBUFS: - errmsg = "not enough memory"; - break; - case EADDRINUSE: - /* handle recursion avoidance in rt_setgate() */ - errmsg = "gateway uses the same route"; - break; - case EEXIST: - errmsg = "route already in table"; - break; - default: - errmsg = strerror(oerrno); - break; + if (fibnum > 0) { + int firstfib = 1; + + printf("%s %s %s", cmd, + (nrflags & F_ISHOST) ? "host" : "net", dest); + if (*gateway) + printf(": gateway %s", gateway); + + if (numfibs > 1) { + TAILQ_FOREACH(fl, &fibl_head, fl_next) { + if (fl->fl_error == 0 + && fl->fl_num >= 0) { + if (firstfib) { + printf(" fib "); + firstfib = 0; + } + printf("%d", fl->fl_num); + if (fibnum-- > 1) + printf(","); + } + } + } + printf("\n"); + } + + fibnum = 0; + TAILQ_FOREACH(fl, &fibl_head, fl_next) { + if (fl->fl_error != 0) { + printf("%s %s %s", cmd, (nrflags & F_ISHOST) + ? "host" : "net", dest); + if (*gateway) + printf(": gateway %s", gateway); + + if (fl->fl_num >= 0) + printf(" fib %d", fl->fl_num); + + switch (fl->fl_errno) { + case ESRCH: + errmsg = "not in table"; + break; + case EBUSY: + errmsg = "entry in use"; + break; + case ENOBUFS: + errmsg = "not enough memory"; + break; + case EADDRINUSE: + /* + * handle recursion avoidance + * in rt_setgate() + */ + errmsg = "gateway uses the same route"; + break; + case EEXIST: + errmsg = "route already in table"; + break; + default: + errmsg = strerror(fl->fl_errno); + break; + } + printf(": %s\n", errmsg); + error = 1; } - (void) printf(": %s\n", errmsg); } } - exit(ret != 0); + exit(error); +} + +static int +newroute_fib(int fib, char *cmd, int flags) +{ + int error; + + error = set_sofib(fib); + if (error) { + warn("fib number %d is ignored", fib); + return (error); + } + + error = rtmsg(*cmd, flags, fib); + return (error); } static void inet_makenetandmask(u_long net, struct sockaddr_in *sin, u_long bits) { - u_long addr, mask = 0; + u_long mask = 0; char *cp; rtm_addrs |= RTA_NETMASK; + /* - * XXX: This approach unable to handle 0.0.0.1/32 correctly - * as inet_network() converts 0.0.0.1 and 1 equally. + * MSB of net should be meaningful. 0/0 is exception. */ - if (net <= 0xff) - addr = net << IN_CLASSA_NSHIFT; - else if (net <= 0xffff) - addr = net << IN_CLASSB_NSHIFT; - else if (net <= 0xffffff) - addr = net << IN_CLASSC_NSHIFT; - else - addr = net; + if (net > 0) + while ((net & 0xff000000) == 0) + net <<= 8; + /* * If no /xx was specified we must calculate the * CIDR address. */ - if ((bits == 0) && (addr != 0)) { + if ((bits == 0) && (net != 0)) { u_long i, j; for(i=0,j=0xff; i<4; i++) { - if (addr & j) { + if (net & j) { break; } j <<= 8; @@ -844,7 +1067,7 @@ inet_makenetandmask(u_long net, struct sockaddr_in *sin, u_long bits) if (bits != 0) mask = 0xffffffff << (32 - bits); - sin->sin_addr.s_addr = htonl(addr); + sin->sin_addr.s_addr = htonl(net); sin = &so_mask.sin; sin->sin_addr.s_addr = htonl(mask); sin->sin_len = 0; @@ -890,7 +1113,7 @@ inet6_makenetandmask(struct sockaddr_in6 *sin6, const char *plen) * returning 1 if a host address, 0 if a network address. */ static int -getaddr(int which, char *str, struct hostent **hpp) +getaddr(int which, char *str, struct hostent **hpp, int nrflags) { sup su; struct hostent *hp; @@ -911,7 +1134,7 @@ getaddr(int which, char *str, struct hostent **hpp) break; case RTA_GATEWAY: su = &so_gate; - if (iflag) { + if (nrflags & F_INTERFACE) { struct ifaddrs *ifap, *ifa; struct sockaddr_dl *sdl = NULL; @@ -971,7 +1194,7 @@ getaddr(int which, char *str, struct hostent **hpp) #if 0 bzero(su, sizeof(*su)); /* for readability */ #endif - getaddr(RTA_NETMASK, str, 0); + getaddr(RTA_NETMASK, str, 0, nrflags); break; #if 0 case RTA_NETMASK: @@ -1002,16 +1225,6 @@ getaddr(int which, char *str, struct hostent **hpp) exit(1); } memcpy(&su->sin6, res->ai_addr, sizeof(su->sin6)); -#ifdef __KAME__ - if ((IN6_IS_ADDR_LINKLOCAL(&su->sin6.sin6_addr) || - IN6_IS_ADDR_MC_LINKLOCAL(&su->sin6.sin6_addr) || - IN6_IS_ADDR_MC_NODELOCAL(&su->sin6.sin6_addr)) && - su->sin6.sin6_scope_id) { - *(u_int16_t *)&su->sin6.sin6_addr.s6_addr[2] = - htons(su->sin6.sin6_scope_id); - su->sin6.sin6_scope_id = 0; - } -#endif freeaddrinfo(res); if (q != NULL) *q++ = '/'; @@ -1165,10 +1378,39 @@ retry2: } static void -monitor(void) +monitor(int argc, char *argv[]) { - int n; - char msg[2048]; + int n, fib, error; + char msg[2048], *endptr; + + fib = defaultfib; + while (argc > 1) { + argc--; + argv++; + if (**argv != '-') + usage(*argv); + switch (keyword(*argv + 1)) { + case K_FIB: + if (!--argc) + usage(*argv); + errno = 0; + fib = strtol(*++argv, &endptr, 0); + if (errno == 0) { + if (*endptr != '\0' || + fib < 0 || + (numfibs != -1 && fib > numfibs - 1)) + errno = EINVAL; + } + if (errno) + errx(EX_USAGE, "invalid fib number: %s", *argv); + break; + default: + usage(*argv); + } + } + error = set_sofib(fib); + if (error) + errx(EX_USAGE, "invalid fib number: %d", fib); verbose = 1; if (debugonly) { @@ -1190,7 +1432,7 @@ struct { } m_rtmsg; static int -rtmsg(int cmd, int flags) +rtmsg(int cmd, int flags, int fib) { static int seq; int rlen; @@ -1253,7 +1495,7 @@ rtmsg(int cmd, int flags) if (l < 0) warn("read from routing socket"); else - print_getmsg(&rtm, l); + print_getmsg(&rtm, l, fib); } #undef rtm return (0); @@ -1413,6 +1655,7 @@ print_rtmsg(struct rt_msghdr *rtm, size_t msglen) break; } printf("\n"); + fflush(stdout); break; default: @@ -1430,7 +1673,7 @@ badlen: } static void -print_getmsg(struct rt_msghdr *rtm, int msglen) +print_getmsg(struct rt_msghdr *rtm, int msglen, int fib) { struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL; struct sockaddr_dl *ifp = NULL; @@ -1490,6 +1733,8 @@ print_getmsg(struct rt_msghdr *rtm, int msglen) } if (gate && rtm->rtm_flags & RTF_GATEWAY) (void)printf(" gateway: %s\n", routename(gate)); + if (fib >= 0) + (void)printf(" fib: %u\n", (unsigned int)fib); if (ifp) (void)printf(" interface: %.*s\n", ifp->sdl_nlen, ifp->sdl_data); diff --git a/sbin/savecore/savecore.8 b/sbin/savecore/savecore.8 index 01be72384a03..c7d7e953682b 100644 --- a/sbin/savecore/savecore.8 +++ b/sbin/savecore/savecore.8 @@ -28,7 +28,7 @@ .\" From: @(#)savecore.8 8.1 (Berkeley) 6/5/93 .\" $FreeBSD$ .\" -.Dd December 24, 2008 +.Dd December 17, 2012 .Dt SAVECORE 8 .Os .Sh NAME @@ -37,12 +37,15 @@ .Sh SYNOPSIS .Nm .Fl c +.Op Fl v +.Op Ar device ... .Nm .Fl C .Op Fl v -.Op Ar directory device +.Op Ar device ... .Nm .Op Fl fkvz +.Op Fl m Ar maxdumps .Op Ar directory Op Ar device ... .Sh DESCRIPTION The @@ -57,7 +60,7 @@ and enters a reboot message and information about the core dump into the system log. .Pp The options are as follows: -.Bl -tag -width indent +.Bl -tag -width ".Fl m Ar maxdumps" .It Fl C Check to see if a dump exists, and display a brief message to indicate the status. @@ -75,6 +78,12 @@ Force a dump to be taken even if either the dump was cleared or if the dump header information is inconsistent. .It Fl k Do not clear the dump after saving it. +.It Fl m Ar maxdumps +Maximum number of dumps to store. +Once the number of stored dumps is equal to +.Ar maxdumps +the counter will restart from +.Dv 0 . .It Fl v Print out some additional debugging information. Specify twice for more information. diff --git a/sbin/savecore/savecore.c b/sbin/savecore/savecore.c index b3f2902af959..bdbf7e384f39 100644 --- a/sbin/savecore/savecore.c +++ b/sbin/savecore/savecore.c @@ -90,6 +90,7 @@ __FBSDID("$FreeBSD$"); static int checkfor, compress, clear, force, keep, verbose; /* flags */ static int nfound, nsaved, nerr; /* statistics */ +static int maxdumps; extern FILE *zopen(const char *, const char *); @@ -178,27 +179,87 @@ writebounds(int bounds) { fclose(fp); } +static off_t +file_size(const char *path) +{ + struct stat sb; + + /* Ignore all errors, those file may not exists. */ + if (stat(path, &sb) == -1) + return (0); + return (sb.st_size); +} + +static off_t +saved_dump_size(int bounds) +{ + static char path[PATH_MAX]; + off_t dumpsize; + + dumpsize = 0; + + (void)snprintf(path, sizeof(path), "info.%d", bounds); + dumpsize += file_size(path); + (void)snprintf(path, sizeof(path), "vmcore.%d", bounds); + dumpsize += file_size(path); + (void)snprintf(path, sizeof(path), "vmcore.%d.gz", bounds); + dumpsize += file_size(path); + (void)snprintf(path, sizeof(path), "textdump.tar.%d", bounds); + dumpsize += file_size(path); + (void)snprintf(path, sizeof(path), "textdump.tar.%d.gz", bounds); + dumpsize += file_size(path); + + return (dumpsize); +} + +static void +saved_dump_remove(int bounds) +{ + static char path[PATH_MAX]; + + (void)snprintf(path, sizeof(path), "info.%d", bounds); + (void)unlink(path); + (void)snprintf(path, sizeof(path), "vmcore.%d", bounds); + (void)unlink(path); + (void)snprintf(path, sizeof(path), "vmcore.%d.gz", bounds); + (void)unlink(path); + (void)snprintf(path, sizeof(path), "textdump.tar.%d", bounds); + (void)unlink(path); + (void)snprintf(path, sizeof(path), "textdump.tar.%d.gz", bounds); + (void)unlink(path); +} + +static void +symlinks_remove(void) +{ + + (void)unlink("info.last"); + (void)unlink("vmcore.last"); + (void)unlink("vmcore.last.gz"); + (void)unlink("textdump.tar.last"); + (void)unlink("textdump.tar.last.gz"); +} + /* * Check that sufficient space is available on the disk that holds the * save directory. */ static int -check_space(const char *savedir, off_t dumpsize) +check_space(const char *savedir, off_t dumpsize, int bounds) { FILE *fp; off_t minfree, spacefree, totfree, needed; struct statfs fsbuf; - char buf[100], path[MAXPATHLEN]; + char buf[100]; - if (statfs(savedir, &fsbuf) < 0) { + if (statfs(".", &fsbuf) < 0) { syslog(LOG_ERR, "%s: %m", savedir); exit(1); } - spacefree = ((off_t) fsbuf.f_bavail * fsbuf.f_bsize) / 1024; + spacefree = ((off_t) fsbuf.f_bavail * fsbuf.f_bsize) / 1024; totfree = ((off_t) fsbuf.f_bfree * fsbuf.f_bsize) / 1024; - (void)snprintf(path, sizeof(path), "%s/minfree", savedir); - if ((fp = fopen(path, "r")) == NULL) + if ((fp = fopen("minfree", "r")) == NULL) minfree = 0; else { if (fgets(buf, sizeof(buf), fp) == NULL) @@ -209,7 +270,8 @@ check_space(const char *savedir, off_t dumpsize) } needed = dumpsize / 1024 + 2; /* 2 for info file */ - if (((minfree > 0) ? spacefree : totfree) - needed < minfree) { + needed -= saved_dump_size(bounds); + if ((minfree > 0 ? spacefree : totfree) - needed < minfree) { syslog(LOG_WARNING, "no dump, not enough free space on device (%lld available, need %lld)", (long long)(minfree > 0 ? spacefree : totfree), @@ -262,7 +324,7 @@ DoRegularFile(int fd, off_t dumpsize, char *buf, const char *device, if (he >= hs + BLOCKSIZE) break; } - + /* back down to a block boundary */ he &= BLOCKMASK; @@ -368,7 +430,7 @@ DoTextdumpFile(int fd, off_t dumpsize, off_t lasthd, char *buf, static void DoFile(const char *savedir, const char *device) { - static char filename[PATH_MAX]; + static char infoname[PATH_MAX], corename[PATH_MAX], linkname[PATH_MAX]; static char *buf = NULL; struct kerneldumpheader kdhf, kdhl; off_t mediasize, dumpsize, firsthd, lasthd; @@ -383,6 +445,9 @@ DoFile(const char *savedir, const char *device) mediasize = 0; status = STATUS_UNKNOWN; + if (maxdumps > 0 && bounds == maxdumps) + bounds = 0; + if (buf == NULL) { buf = malloc(BUFFERSIZE); if (buf == NULL) { @@ -394,7 +459,7 @@ DoFile(const char *savedir, const char *device) if (verbose) printf("checking for kernel dump on device %s\n", device); - fd = open(device, O_RDWR); + fd = open(device, (checkfor || keep) ? O_RDONLY : O_RDWR); if (fd < 0) { syslog(LOG_ERR, "%s: %m", device); return; @@ -433,7 +498,7 @@ DoFile(const char *savedir, const char *device) syslog(LOG_ERR, "unknown version (%d) in last dump header on %s", dtoh32(kdhl.version), device); - + status = STATUS_BAD; if (force == 0) goto closefd; @@ -444,7 +509,7 @@ DoFile(const char *savedir, const char *device) syslog(LOG_ERR, "unknown version (%d) in last dump header on %s", dtoh32(kdhl.version), device); - + status = STATUS_BAD; if (force == 0) goto closefd; @@ -472,7 +537,7 @@ DoFile(const char *savedir, const char *device) syslog(LOG_ERR, "unknown version (%d) in last dump header on %s", dtoh32(kdhl.version), device); - + status = STATUS_BAD; if (force == 0) goto closefd; @@ -536,19 +601,22 @@ DoFile(const char *savedir, const char *device) if (verbose) printf("Checking for available free space\n"); - if (!check_space(savedir, dumpsize)) { + + if (!check_space(savedir, dumpsize, bounds)) { nerr++; goto closefd; } writebounds(bounds + 1); - sprintf(buf, "info.%d", bounds); + saved_dump_remove(bounds); + + snprintf(infoname, sizeof(infoname), "info.%d", bounds); /* * Create or overwrite any existing dump header files. */ - fdinfo = open(buf, O_WRONLY | O_CREAT | O_TRUNC, 0600); + fdinfo = open(infoname, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fdinfo < 0) { syslog(LOG_ERR, "%s: %m", buf); nerr++; @@ -556,16 +624,16 @@ DoFile(const char *savedir, const char *device) } oumask = umask(S_IRWXG|S_IRWXO); /* Restrict access to the core file.*/ if (compress) { - sprintf(filename, "%s.%d.gz", istextdump ? "textdump.tar" : - "vmcore", bounds); - fp = zopen(filename, "w"); + snprintf(corename, sizeof(corename), "%s.%d.gz", + istextdump ? "textdump.tar" : "vmcore", bounds); + fp = zopen(corename, "w"); } else { - sprintf(filename, "%s.%d", istextdump ? "textdump.tar" : - "vmcore", bounds); - fp = fopen(filename, "w"); + snprintf(corename, sizeof(corename), "%s.%d", + istextdump ? "textdump.tar" : "vmcore", bounds); + fp = fopen(corename, "w"); } if (fp == NULL) { - syslog(LOG_ERR, "%s: %m", filename); + syslog(LOG_ERR, "%s: %m", corename); close(fdinfo); nerr++; goto closefd; @@ -586,15 +654,15 @@ DoFile(const char *savedir, const char *device) printheader(info, &kdhl, device, bounds, status); fclose(info); - syslog(LOG_NOTICE, "writing %score to %s", - compress ? "compressed " : "", filename); + syslog(LOG_NOTICE, "writing %score to %s/%s", + compress ? "compressed " : "", savedir, corename); if (istextdump) { if (DoTextdumpFile(fd, dumpsize, lasthd, buf, device, - filename, fp) < 0) + corename, fp) < 0) goto closeall; } else { - if (DoRegularFile(fd, dumpsize, buf, device, filename, fp) + if (DoRegularFile(fd, dumpsize, buf, device, corename, fp) < 0) goto closeall; } @@ -602,17 +670,35 @@ DoFile(const char *savedir, const char *device) printf("\n"); if (fclose(fp) < 0) { - syslog(LOG_ERR, "error on %s: %m", filename); + syslog(LOG_ERR, "error on %s: %m", corename); nerr++; goto closeall; } + + symlinks_remove(); + if (symlink(infoname, "info.last") == -1) { + syslog(LOG_WARNING, "unable to create symlink %s/%s: %m", + savedir, "info.last"); + } + if (compress) { + snprintf(linkname, sizeof(linkname), "%s.last.gz", + istextdump ? "textdump.tar" : "vmcore"); + } else { + snprintf(linkname, sizeof(linkname), "%s.last", + istextdump ? "textdump.tar" : "vmcore"); + } + if (symlink(corename, linkname) == -1) { + syslog(LOG_WARNING, "unable to create symlink %s/%s: %m", + savedir, linkname); + } + nsaved++; if (verbose) printf("dump saved\n"); nuke: - if (clear || !keep) { + if (!keep) { if (verbose) printf("clearing dump header\n"); memcpy(kdhl.magic, KERNELDUMPMAGIC_CLEARED, sizeof kdhl.magic); @@ -636,10 +722,10 @@ static void usage(void) { fprintf(stderr, "%s\n%s\n%s\n", - "usage: savecore -c", - " savecore -C [-v] [directory device]", - " savecore [-fkvz] [directory [device ...]]"); - exit (1); + "usage: savecore -c [-v] [device ...]", + " savecore -C [-v] [device ...]", + " savecore [-fkvz] [-m maxdumps] [directory [device ...]]"); + exit(1); } int @@ -655,7 +741,7 @@ main(int argc, char **argv) openlog("savecore", LOG_PERROR, LOG_DAEMON); signal(SIGINFO, infohandler); - while ((ch = getopt(argc, argv, "Ccfkvz")) != -1) + while ((ch = getopt(argc, argv, "Ccfkm:vz")) != -1) switch(ch) { case 'C': checkfor = 1; @@ -663,15 +749,22 @@ main(int argc, char **argv) case 'c': clear = 1; break; + case 'f': + force = 1; + break; case 'k': keep = 1; break; + case 'm': + maxdumps = atoi(optarg); + if (maxdumps <= 0) { + syslog(LOG_ERR, "Invalid maxdump value"); + exit(1); + } + break; case 'v': verbose++; break; - case 'f': - force = 1; - break; case 'z': compress = 1; break; @@ -681,9 +774,13 @@ main(int argc, char **argv) } if (checkfor && (clear || force || keep)) usage(); + if (clear && (compress || keep)) + usage(); + if (maxdumps > 0 && (checkfor || clear)) + usage(); argc -= optind; argv += optind; - if (argc >= 1) { + if (argc >= 1 && !checkfor && !clear) { error = chdir(argv[0]); if (error) { syslog(LOG_ERR, "chdir(%s): %m", argv[0]); diff --git a/sbin/setkey/Makefile b/sbin/setkey/Makefile index 03c2ea2655dc..e2c93ccf489b 100644 --- a/sbin/setkey/Makefile +++ b/sbin/setkey/Makefile @@ -61,7 +61,7 @@ CLEANFILES+= scriptdump y.tab.h #SCRIPTS= scriptdump -LOCALPREFIX= /usr +LOCALPREFIX= /usr/local scriptdump: scriptdump.pl sed -e 's#@LOCALPREFIX@#${LOCALPREFIX}#' < $> > scriptdump diff --git a/sbin/setkey/setkey.8 b/sbin/setkey/setkey.8 index 8f7bae139c08..19a916447c36 100644 --- a/sbin/setkey/setkey.8 +++ b/sbin/setkey/setkey.8 @@ -110,7 +110,7 @@ Loop forever and dump all the messages transmitted to .Dv PF_KEY socket. .Fl xx -makes each timestamps unformatted. +makes each timestamp unformatted. .El .Ss Configuration syntax With diff --git a/sbin/sysctl/sysctl.8 b/sbin/sysctl/sysctl.8 index be43e6818189..fe0a75a971c8 100644 --- a/sbin/sysctl/sysctl.8 +++ b/sbin/sysctl/sysctl.8 @@ -28,7 +28,7 @@ .\" From: @(#)sysctl.8 8.1 (Berkeley) 6/6/93 .\" $FreeBSD$ .\" -.Dd January 17, 2011 +.Dd December 13, 2012 .Dt SYSCTL 8 .Os .Sh NAME @@ -36,11 +36,12 @@ .Nd get or set kernel state .Sh SYNOPSIS .Nm -.Op Fl bdehiNnoqx +.Op Fl bdehiNnoRTqx +.Op Fl f Ar filename .Ar name Ns Op = Ns Ar value .Ar ... .Nm -.Op Fl bdehNnoqx +.Op Fl bdehNnoRTqx .Fl a .Sh DESCRIPTION The @@ -80,6 +81,11 @@ This option is ignored if either or .Fl n is specified, or a variable is being set. +.It Fl f Ar filename +Specify a file which contains a pair of name and value in each line. +.Nm +reads and processes the specified file first and then processes the name +and value pairs in the command line argument. .It Fl h Format output for human, rather than machine, readability. .It Fl i @@ -121,6 +127,11 @@ sixteen bytes of the value. Suppress some warnings generated by .Nm to standard error. +.It Fl T +Display only variables that are setable via loader (CTLFLAG_TUN). +.It Fl W +Display only wriable variables that are not statistical. +Useful for determining the set of runtime tunable sysctls. .It Fl X Equivalent to .Fl x a diff --git a/sbin/sysctl/sysctl.c b/sbin/sysctl/sysctl.c index 7379155353c6..43592b3081c9 100644 --- a/sbin/sysctl/sysctl.c +++ b/sbin/sysctl/sysctl.c @@ -56,13 +56,17 @@ static const char rcsid[] = #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sysexits.h> #include <unistd.h> +static const char *conffile; + static int aflag, bflag, dflag, eflag, hflag, iflag; -static int Nflag, nflag, oflag, qflag, xflag, warncount; +static int Nflag, nflag, oflag, qflag, Tflag, Wflag, xflag; static int oidfmt(int *, int, char *, u_int *); -static void parse(char *); +static int parsefile(const char *); +static int parse(const char *, int); static int show_var(int *, int); static int sysctl_all(int *oid, int len); static int name2oid(char *, int *); @@ -74,8 +78,8 @@ usage(void) { (void)fprintf(stderr, "%s\n%s\n", - "usage: sysctl [-bdehiNnoqx] name[=value] ...", - " sysctl [-bdehNnoqx] -a"); + "usage: sysctl [-bdehiNnoqTWx] [-f filename] name[=value] ...", + " sysctl [-bdehNnoqTWx] -a"); exit(1); } @@ -83,12 +87,13 @@ int main(int argc, char **argv) { int ch; + int warncount = 0; setlocale(LC_NUMERIC, ""); setbuf(stdout,0); setbuf(stderr,0); - while ((ch = getopt(argc, argv, "AabdehiNnoqwxX")) != -1) { + while ((ch = getopt(argc, argv, "Aabdef:hiNnoqTwWxX")) != -1) { switch (ch) { case 'A': /* compatibility */ @@ -106,6 +111,9 @@ main(int argc, char **argv) case 'e': eflag = 1; break; + case 'f': + conffile = optarg; + break; case 'h': hflag = 1; break; @@ -124,10 +132,16 @@ main(int argc, char **argv) case 'q': qflag = 1; break; + case 'T': + Tflag = 1; + break; case 'w': /* compatibility */ /* ignored */ break; + case 'W': + Wflag = 1; + break; case 'X': /* compatibility */ aflag = xflag = 1; @@ -146,13 +160,17 @@ main(int argc, char **argv) usage(); if (aflag && argc == 0) exit(sysctl_all(0, 0)); - if (argc == 0) + if (argc == 0 && conffile == NULL) usage(); warncount = 0; + if (conffile != NULL) + warncount += parsefile(conffile); + while (argc-- > 0) - parse(*argv++); - exit(warncount); + warncount += parse(*argv++, 0); + + return (warncount); } /* @@ -160,8 +178,8 @@ main(int argc, char **argv) * Lookup and print out the MIB entry if it exists. * Set a new value if requested. */ -static void -parse(char *string) +static int +parse(const char *string, int lineno) { int len, i, j; void *newval = 0; @@ -173,17 +191,36 @@ parse(char *string) int64_t i64val; uint64_t u64val; int mib[CTL_MAXNAME]; - char *cp, *bufp, buf[BUFSIZ], *endptr, fmt[BUFSIZ]; + char *cp, *bufp, buf[BUFSIZ], *endptr, fmt[BUFSIZ], line[BUFSIZ]; u_int kind; - bufp = buf; - if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ) - errx(1, "oid too long: '%s'", string); - if ((cp = strchr(string, '=')) != NULL) { - *strchr(buf, '=') = '\0'; - *cp++ = '\0'; + if (lineno) + snprintf(line, sizeof(line), " at line %d", lineno); + else + line[0] = '\0'; + + cp = buf; + if (snprintf(buf, BUFSIZ, "%s", string) >= BUFSIZ) { + warn("oid too long: '%s'%s", string, line); + return (1); + } + bufp = strsep(&cp, "=:"); + if (cp != NULL) { + /* Tflag just lists tunables, do not allow assignment */ + if (Tflag || Wflag) { + warnx("Can't set variables when using -T or -W"); + usage(); + } while (isspace(*cp)) cp++; + /* Strip a pair of " or ' if any. */ + switch (*cp) { + case '\"': + case '\'': + if (cp[strlen(cp) - 1] == *cp) + cp[strlen(cp) - 1] = '\0'; + cp++; + } newval = cp; newsize = strlen(cp); } @@ -191,15 +228,22 @@ parse(char *string) if (len < 0) { if (iflag) - return; + return (0); if (qflag) - exit(1); - else - errx(1, "unknown oid '%s'", bufp); + return (1); + else { + warn("unknown oid '%s'%s", bufp, line); + return (1); + } } - if (oidfmt(mib, len, fmt, &kind)) - err(1, "couldn't find format of oid '%s'", bufp); + if (oidfmt(mib, len, fmt, &kind)) { + warn("couldn't find format of oid '%s'%s", bufp, line); + if (iflag) + return (1); + else + exit(1); + } if (newval == NULL || dflag) { if ((kind & CTLTYPE) == CTLTYPE_NODE) { @@ -215,16 +259,18 @@ parse(char *string) putchar('\n'); } } else { - if ((kind & CTLTYPE) == CTLTYPE_NODE) - errx(1, "oid '%s' isn't a leaf node", bufp); + if ((kind & CTLTYPE) == CTLTYPE_NODE) { + warn("oid '%s' isn't a leaf node%s", bufp, line); + return (1); + } if (!(kind & CTLFLAG_WR)) { if (kind & CTLFLAG_TUN) { - warnx("oid '%s' is a read only tunable", bufp); - errx(1, "Tunable values are set in /boot/loader.conf"); - } else { - errx(1, "oid '%s' is read only", bufp); - } + warnx("oid '%s' is a read only tunable%s", bufp, line); + warnx("Tunable values are set in /boot/loader.conf"); + } else + warnx("oid '%s' is read only%s", bufp, line); + return (1); } if ((kind & CTLTYPE) == CTLTYPE_INT || @@ -233,47 +279,59 @@ parse(char *string) (kind & CTLTYPE) == CTLTYPE_ULONG || (kind & CTLTYPE) == CTLTYPE_S64 || (kind & CTLTYPE) == CTLTYPE_U64) { - if (strlen(newval) == 0) - errx(1, "empty numeric value"); + if (strlen(newval) == 0) { + warnx("empty numeric value"); + return (1); + } } switch (kind & CTLTYPE) { case CTLTYPE_INT: if (strcmp(fmt, "IK") == 0) { - if (!set_IK(newval, &intval)) - errx(1, "invalid value '%s'", - (char *)newval); + if (!set_IK(newval, &intval)) { + warnx("invalid value '%s'%s", + (char *)newval, line); + return (1); + } } else { intval = (int)strtol(newval, &endptr, 0); - if (endptr == newval || *endptr != '\0') - errx(1, "invalid integer '%s'", - (char *)newval); + if (endptr == newval || *endptr != '\0') { + warnx("invalid integer '%s'%s", + (char *)newval, line); + return (1); + } } newval = &intval; newsize = sizeof(intval); break; case CTLTYPE_UINT: uintval = (int) strtoul(newval, &endptr, 0); - if (endptr == newval || *endptr != '\0') - errx(1, "invalid unsigned integer '%s'", - (char *)newval); + if (endptr == newval || *endptr != '\0') { + warnx("invalid unsigned integer '%s'%s", + (char *)newval, line); + return (1); + } newval = &uintval; newsize = sizeof(uintval); break; case CTLTYPE_LONG: longval = strtol(newval, &endptr, 0); - if (endptr == newval || *endptr != '\0') - errx(1, "invalid long integer '%s'", - (char *)newval); + if (endptr == newval || *endptr != '\0') { + warnx("invalid long integer '%s'%s", + (char *)newval, line); + return (1); + } newval = &longval; newsize = sizeof(longval); break; case CTLTYPE_ULONG: ulongval = strtoul(newval, &endptr, 0); - if (endptr == newval || *endptr != '\0') - errx(1, "invalid unsigned long integer" - " '%s'", (char *)newval); + if (endptr == newval || *endptr != '\0') { + warnx("invalid unsigned long integer" + " '%s'%s", (char *)newval, line); + return (1); + } newval = &ulongval; newsize = sizeof(ulongval); break; @@ -281,26 +339,31 @@ parse(char *string) break; case CTLTYPE_S64: i64val = strtoimax(newval, &endptr, 0); - if (endptr == newval || *endptr != '\0') - errx(1, "invalid int64_t '%s'", - (char *)newval); + if (endptr == newval || *endptr != '\0') { + warnx("invalid int64_t '%s'%s", + (char *)newval, line); + return (1); + } newval = &i64val; newsize = sizeof(i64val); break; case CTLTYPE_U64: u64val = strtoumax(newval, &endptr, 0); - if (endptr == newval || *endptr != '\0') - errx(1, "invalid uint64_t '%s'", - (char *)newval); + if (endptr == newval || *endptr != '\0') { + warnx("invalid uint64_t '%s'%s", + (char *)newval, line); + return (1); + } newval = &u64val; newsize = sizeof(u64val); break; case CTLTYPE_OPAQUE: /* FALLTHROUGH */ default: - errx(1, "oid '%s' is type %d," - " cannot set that", bufp, - kind & CTLTYPE); + warnx("oid '%s' is type %d," + " cannot set that%s", bufp, + kind & CTLTYPE, line); + return (1); } i = show_var(mib, len); @@ -309,18 +372,20 @@ parse(char *string) putchar('\n'); switch (errno) { case EOPNOTSUPP: - errx(1, "%s: value is not available", - string); + warnx("%s: value is not available%s", + string, line); + return (1); case ENOTDIR: - errx(1, "%s: specification is incomplete", - string); + warnx("%s: specification is incomplete%s", + string, line); + return (1); case ENOMEM: - errx(1, "%s: type is unknown to this program", - string); + warnx("%s: type is unknown to this program%s", + string, line); + return (1); default: - warn("%s", string); - warncount++; - return; + warn("%s%s", string, line); + return (1); } } if (!bflag) @@ -332,6 +397,58 @@ parse(char *string) putchar('\n'); nflag = i; } + + return (0); +} + +static int +parsefile(const char *filename) +{ + FILE *file; + char line[BUFSIZ], *p, *pq, *pdq; + int warncount = 0, lineno = 0; + + file = fopen(filename, "r"); + if (file == NULL) + err(EX_NOINPUT, "%s", filename); + while (fgets(line, sizeof(line), file) != NULL) { + lineno++; + p = line; + pq = strchr(line, '\''); + pdq = strchr(line, '\"'); + /* Replace the first # with \0. */ + while((p = strchr(p, '#')) != NULL) { + if (pq != NULL && p > pq) { + if ((p = strchr(pq+1, '\'')) != NULL) + *(++p) = '\0'; + break; + } else if (pdq != NULL && p > pdq) { + if ((p = strchr(pdq+1, '\"')) != NULL) + *(++p) = '\0'; + break; + } else if (p == line || *(p-1) != '\\') { + *p = '\0'; + break; + } + p++; + } + /* Trim spaces */ + p = line + strlen(line) - 1; + while (p >= line && isspace((int)*p)) { + *p = '\0'; + p--; + } + p = line; + while (isspace((int)*p)) + p++; + if (*p == '\0') + continue; + else + warncount += parse(p, lineno); + } + fclose(file); + + return (warncount); } /* These functions will dump out various interesting structures. */ @@ -529,7 +646,7 @@ static int show_var(int *oid, int nlen) { u_char buf[BUFSIZ], *val, *oval, *p; - char name[BUFSIZ], *fmt; + char name[BUFSIZ], fmt[BUFSIZ]; const char *sep, *sep1; int qoid[CTL_MAXNAME+2]; uintmax_t umv; @@ -544,6 +661,7 @@ show_var(int *oid, int nlen) umv = mv = intlen = 0; bzero(buf, BUFSIZ); + bzero(fmt, BUFSIZ); bzero(name, BUFSIZ); qoid[0] = 0; memcpy(qoid + 2, oid, nlen * sizeof(int)); @@ -554,6 +672,15 @@ show_var(int *oid, int nlen) if (i || !j) err(1, "sysctl name %d %zu %d", i, j, errno); + oidfmt(oid, nlen, fmt, &kind); + /* if Wflag then only list sysctls that are writeable and not stats. */ + if (Wflag && ((kind & CTLFLAG_WR) == 0 || (kind & CTLFLAG_STATS) != 0)) + return 1; + + /* if Tflag then only list sysctls that are tuneables. */ + if (Tflag && (kind & CTLFLAG_TUN) == 0) + return 1; + if (Nflag) { printf("%s", name); return (0); @@ -596,8 +723,6 @@ show_var(int *oid, int nlen) return (0); } val[len] = '\0'; - fmt = buf; - oidfmt(oid, nlen, fmt, &kind); p = val; ctltype = (kind & CTLTYPE); sign = ctl_sign[ctltype]; diff --git a/sbin/umount/umount.c b/sbin/umount/umount.c index f179a4c43b1f..f2e02f26dccf 100644 --- a/sbin/umount/umount.c +++ b/sbin/umount/umount.c @@ -359,8 +359,10 @@ umountfs(struct statfs *sfs) do_rpc = 1; } - if (!namematch(ai)) + if (!namematch(ai)) { + free(orignfsdirname); return (1); + } /* First try to unmount using the file system ID. */ snprintf(fsidbuf, sizeof(fsidbuf), "FSID:%d:%d", sfs->f_fsid.val[0], sfs->f_fsid.val[1]); @@ -369,13 +371,16 @@ umountfs(struct statfs *sfs) if (errno != ENOENT || sfs->f_fsid.val[0] != 0 || sfs->f_fsid.val[1] != 0) warn("unmount of %s failed", sfs->f_mntonname); - if (errno != ENOENT) + if (errno != ENOENT) { + free(orignfsdirname); return (1); + } /* Compatibility for old kernels. */ if (sfs->f_fsid.val[0] != 0 || sfs->f_fsid.val[1] != 0) warnx("retrying using path instead of file system ID"); if (unmount(sfs->f_mntonname, fflag) != 0) { warn("unmount of %s failed", sfs->f_mntonname); + free(orignfsdirname); return (1); } } @@ -393,6 +398,7 @@ umountfs(struct statfs *sfs) if (clp == NULL) { warnx("%s: %s", hostp, clnt_spcreateerror("MOUNTPROG")); + free(orignfsdirname); return (1); } clp->cl_auth = authsys_create_default(); @@ -403,6 +409,7 @@ umountfs(struct statfs *sfs) if (clnt_stat != RPC_SUCCESS) { warnx("%s: %s", hostp, clnt_sperror(clp, "RPCMNT_UMOUNT")); + free(orignfsdirname); return (1); } /* @@ -415,10 +422,10 @@ umountfs(struct statfs *sfs) hostp, nfsdirname); free_mtab(); } - free(orignfsdirname); auth_destroy(clp->cl_auth); clnt_destroy(clp); } + free(orignfsdirname); return (0); } |