diff --git a/bin/ps/extern.h b/bin/ps/extern.h index 432128542cd..7b5522dc150 100644 --- a/bin/ps/extern.h +++ b/bin/ps/extern.h @@ -70,6 +70,7 @@ void pmem(KINFO *, VARENT *); void pri(KINFO *, VARENT *); void printheader(void); void priorityr(KINFO *, VARENT *); +void egroupname(KINFO *, VARENT *); void rgroupname(KINFO *, VARENT *); void runame(KINFO *, VARENT *); void rvar(KINFO *, VARENT *); @@ -78,6 +79,7 @@ int s_cputime(KINFO *); int s_label(KINFO *); int s_loginclass(KINFO *); int s_logname(KINFO *); +int s_egroupname(KINFO *); int s_rgroupname(KINFO *); int s_runame(KINFO *); int s_systime(KINFO *); diff --git a/bin/ps/keyword.c b/bin/ps/keyword.c index 136d084c815..c4467561bf3 100644 --- a/bin/ps/keyword.c +++ b/bin/ps/keyword.c @@ -88,12 +88,19 @@ static VAR var[] = { {"cpu", "CPU", NULL, 0, kvar, NULL, 3, KOFF(ki_estcpu), UINT, "d", 0}, {"cputime", "", "time", 0, NULL, NULL, 0, 0, CHAR, NULL, 0}, + {"egid", "", "gid", 0, NULL, NULL, 0, 0, CHAR, NULL, 0}, + {"egroup", "", "group", 0, NULL, NULL, 0, 0, CHAR, NULL, 0}, {"emul", "EMUL", NULL, LJUST, emulname, NULL, EMULLEN, 0, CHAR, NULL, 0}, {"etime", "ELAPSED", NULL, USER, elapsed, NULL, 12, 0, CHAR, NULL, 0}, {"etimes", "ELAPSED", NULL, USER, elapseds, NULL, 12, 0, CHAR, NULL, 0}, + {"euid", "", "uid", 0, NULL, NULL, 0, 0, CHAR, NULL, 0}, {"f", "F", NULL, 0, kvar, NULL, 8, KOFF(ki_flag), INT, "x", 0}, {"flags", "", "f", 0, NULL, NULL, 0, 0, CHAR, NULL, 0}, + {"gid", "GID", NULL, 0, kvar, NULL, UIDLEN, KOFF(ki_groups), + UINT, UIDFMT, 0}, + {"group", "GROUP", NULL, LJUST, egroupname, s_egroupname, + USERLEN, 0, CHAR, NULL, 0}, {"ignored", "", "sigignore", 0, NULL, NULL, 0, 0, CHAR, NULL, 0}, {"inblk", "INBLK", NULL, USER, rvar, NULL, 4, ROFF(ru_inblock), LONG, "ld", 0}, diff --git a/bin/ps/print.c b/bin/ps/print.c index 432cffa274d..02c6112d546 100644 --- a/bin/ps/print.c +++ b/bin/ps/print.c @@ -340,6 +340,22 @@ s_uname(KINFO *k) return (strlen(user_from_uid(k->ki_p->ki_uid, 0))); } +void +egroupname(KINFO *k, VARENT *ve) +{ + VAR *v; + + v = ve->var; + (void)printf("%-*s", v->width, + group_from_gid(k->ki_p->ki_groups[0], 0)); +} + +int +s_egroupname(KINFO *k) +{ + return (strlen(group_from_gid(k->ki_p->ki_groups[0], 0))); +} + void rgroupname(KINFO *k, VARENT *ve) { diff --git a/bin/ps/ps.1 b/bin/ps/ps.1 index 2465df3acb2..10dd6af7f85 100644 --- a/bin/ps/ps.1 +++ b/bin/ps/ps.1 @@ -29,7 +29,7 @@ .\" @(#)ps.1 8.3 (Berkeley) 4/18/94 .\" $FreeBSD$ .\" -.Dd April 18, 2011 +.Dd June 14, 2011 .Dt PS 1 .Os .Sh NAME @@ -502,6 +502,12 @@ elapsed running time, in decimal integer seconds .It Cm flags the process flags, in hexadecimal (alias .Cm f ) +.It Cm gid +effective group ID (alias +.Cm egid ) +.It Cm group +group name (from egid) (alias +.Cm egroup ) .It Cm inblk total blocks read (alias .Cm inblock ) @@ -629,7 +635,8 @@ process pointer .It Cm ucomm name to be used for accounting .It Cm uid -effective user ID +effective user ID (alias +.Cm euid ) .It Cm upr scheduling priority on return from system call (alias .Cm usrpri ) diff --git a/bin/sh/alias.c b/bin/sh/alias.c index 929c68e8798..fb0e9229443 100644 --- a/bin/sh/alias.c +++ b/bin/sh/alias.c @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include "mystring.h" #include "alias.h" #include "options.h" /* XXX for argptr (should remove?) */ +#include "builtins.h" #define ATABSIZE 39 diff --git a/bin/sh/alias.h b/bin/sh/alias.h index 79836639acd..546e91a1f3f 100644 --- a/bin/sh/alias.h +++ b/bin/sh/alias.h @@ -43,5 +43,3 @@ struct alias { }; struct alias *lookupalias(const char *, int); -int aliascmd(int, char **); -int unaliascmd(int, char **); diff --git a/bin/sh/arith.h b/bin/sh/arith.h index 3a7db9e059f..5b18bd677cc 100644 --- a/bin/sh/arith.h +++ b/bin/sh/arith.h @@ -36,4 +36,3 @@ arith_t arith(const char *); void arith_lex_reset(void); -int expcmd(int, char **); diff --git a/bin/sh/bltin/bltin.h b/bin/sh/bltin/bltin.h index e449673d1d0..0143b6e27ac 100644 --- a/bin/sh/bltin/bltin.h +++ b/bin/sh/bltin/bltin.h @@ -43,6 +43,7 @@ #include "../mystring.h" #ifdef SHELL #include "../output.h" +#include "builtins.h" #define FILE struct output #undef stdout #define stdout out1 @@ -75,7 +76,4 @@ pointer stalloc(int); void error(const char *, ...) __printf0like(1, 2); pid_t getjobpgrp(char *); -int echocmd(int, char **); -int testcmd(int, char **); - extern char *commandname; diff --git a/bin/sh/cd.c b/bin/sh/cd.c index b1b0fc015e9..6fb10390a23 100644 --- a/bin/sh/cd.c +++ b/bin/sh/cd.c @@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$"); #include "mystring.h" #include "show.h" #include "cd.h" +#include "builtins.h" static int cdlogical(char *); static int cdphysical(char *); diff --git a/bin/sh/cd.h b/bin/sh/cd.h index f88ce26ad4c..91fbc2b692a 100644 --- a/bin/sh/cd.h +++ b/bin/sh/cd.h @@ -30,5 +30,3 @@ */ void pwd_init(int); -int cdcmd (int, char **); -int pwdcmd(int, char **); diff --git a/bin/sh/eval.h b/bin/sh/eval.h index bf987828d0c..fba6f9a2a9c 100644 --- a/bin/sh/eval.h +++ b/bin/sh/eval.h @@ -51,19 +51,10 @@ struct backcmd { /* result of evalbackcmd */ #define EV_TESTED 02 /* exit status is checked; ignore -e flag */ #define EV_BACKCMD 04 /* command executing within back quotes */ -int evalcmd(int, char **); void evalstring(char *, int); union node; /* BLETCH for ansi C */ void evaltree(union node *, int); void evalbackcmd(union node *, struct backcmd *); -int bltincmd(int, char **); -int breakcmd(int, char **); -int returncmd(int, char **); -int falsecmd(int, char **); -int truecmd(int, char **); -int execcmd(int, char **); -int timescmd(int, char **); -int commandcmd(int, char **); /* in_function returns nonzero if we are currently evaluating a function */ #define in_function() funcnest diff --git a/bin/sh/exec.h b/bin/sh/exec.h index 392cc335f66..31f11c09c28 100644 --- a/bin/sh/exec.h +++ b/bin/sh/exec.h @@ -66,7 +66,6 @@ extern int exerrno; /* last exec error */ void shellexec(char **, char **, const char *, int) __dead2; char *padvance(const char **, const char *); -int hashcmd(int, char **); void find_command(const char *, struct cmdentry *, int, const char *); int find_builtin(const char *, int *); void hashcd(void); @@ -75,5 +74,4 @@ void addcmdentry(const char *, struct cmdentry *); void defun(const char *, union node *); int unsetfunc(const char *); int typecmd_impl(int, char **, int, const char *); -int typecmd(int, char **); void clearcmdentry(void); diff --git a/bin/sh/expand.c b/bin/sh/expand.c index c6c54ab6f3c..95a0d6ad15d 100644 --- a/bin/sh/expand.c +++ b/bin/sh/expand.c @@ -76,6 +76,7 @@ __FBSDID("$FreeBSD$"); #include "mystring.h" #include "arith.h" #include "show.h" +#include "builtins.h" /* * Structure specifying which parts of the string should be searched diff --git a/bin/sh/expand.h b/bin/sh/expand.h index a4bb198010a..5029552fe28 100644 --- a/bin/sh/expand.h +++ b/bin/sh/expand.h @@ -63,4 +63,3 @@ void expari(int); int patmatch(const char *, const char *, int); void rmescapes(char *); int casematch(union node *, const char *); -int wordexpcmd(int, char **); diff --git a/bin/sh/histedit.c b/bin/sh/histedit.c index 7ebe5d87502..4619baf7856 100644 --- a/bin/sh/histedit.c +++ b/bin/sh/histedit.c @@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$"); #include "error.h" #include "eval.h" #include "memalloc.h" +#include "builtins.h" #define MAXHISTLOOPS 4 /* max recursions through fc */ #define DEFEDITOR "ed" /* default editor *should* be $EDITOR */ diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c index cbc29f17564..75b503ecaa7 100644 --- a/bin/sh/jobs.c +++ b/bin/sh/jobs.c @@ -71,6 +71,7 @@ __FBSDID("$FreeBSD$"); #include "error.h" #include "mystring.h" #include "var.h" +#include "builtins.h" static struct job *jobtab; /* array of jobs */ diff --git a/bin/sh/jobs.h b/bin/sh/jobs.h index 8bc10821a02..5e9d70db043 100644 --- a/bin/sh/jobs.h +++ b/bin/sh/jobs.h @@ -88,12 +88,7 @@ extern int in_dowait; /* are we in dowait()? */ extern volatile sig_atomic_t breakwaitcmd; /* break wait to process traps? */ void setjobctl(int); -int fgcmd(int, char **); -int bgcmd(int, char **); -int jobscmd(int, char **); void showjobs(int, int); -int waitcmd(int, char **); -int jobidcmd(int, char **); struct job *makejob(union node *, int); pid_t forkshell(struct job *, union node *, int); int waitforjob(struct job *, int *); diff --git a/bin/sh/main.c b/bin/sh/main.c index 2da5a15a927..e6c8a209de5 100644 --- a/bin/sh/main.c +++ b/bin/sh/main.c @@ -72,6 +72,7 @@ __FBSDID("$FreeBSD$"); #include "mystring.h" #include "exec.h" #include "cd.h" +#include "builtins.h" int rootpid; int rootshell; diff --git a/bin/sh/main.h b/bin/sh/main.h index c5e8bfd3840..6d4cc4a9b99 100644 --- a/bin/sh/main.h +++ b/bin/sh/main.h @@ -39,5 +39,3 @@ extern struct jmploc main_handler; /* top level exception handler */ void readcmdfile(const char *); void cmdloop(int); -int dotcmd(int, char **); -int exitcmd(int, char **); diff --git a/bin/sh/mkbuiltins b/bin/sh/mkbuiltins index b78729ac9ea..49af058461c 100755 --- a/bin/sh/mkbuiltins +++ b/bin/sh/mkbuiltins @@ -58,9 +58,7 @@ cat <<\! ! awk '/^[^#]/ {if(('$havejobs' || $2 != "-j") && ('$havehist' || $2 != "-h")) \ print $0}' builtins.def | sed 's/-[hj]//' > $temp -awk '{ printf "int %s(int, char **);\n", $1}' $temp -echo ' -int (*const builtinfunc[])(int, char **) = {' +echo 'int (*const builtinfunc[])(int, char **) = {' awk '/^[^#]/ { printf "\t%s,\n", $1}' $temp echo '}; @@ -94,5 +92,7 @@ struct builtincmd { }; extern int (*const builtinfunc[])(int, char **); -extern const struct builtincmd builtincmd[];' +extern const struct builtincmd builtincmd[]; +' +awk '{ printf "int %s(int, char **);\n", $1}' $temp rm -f $temp diff --git a/bin/sh/myhistedit.h b/bin/sh/myhistedit.h index bc9fd4eddda..9a649ecccdd 100644 --- a/bin/sh/myhistedit.h +++ b/bin/sh/myhistedit.h @@ -39,8 +39,6 @@ extern int displayhist; void histedit(void); void sethistsize(const char *); void setterm(const char *); -int histcmd(int, char **); int not_fcnumber(const char *); int str_to_event(const char *, int); -int bindcmd(int, char **); diff --git a/bin/sh/options.c b/bin/sh/options.c index 60c885284f7..9104e93270f 100644 --- a/bin/sh/options.c +++ b/bin/sh/options.c @@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$"); #include "memalloc.h" #include "error.h" #include "mystring.h" +#include "builtins.h" #ifndef NO_HISTORY #include "myhistedit.h" #endif diff --git a/bin/sh/options.h b/bin/sh/options.h index 5004549a292..f3d3d3db456 100644 --- a/bin/sh/options.h +++ b/bin/sh/options.h @@ -108,8 +108,5 @@ void procargs(int, char **); void optschanged(void); void setparam(char **); void freeparam(struct shparam *); -int shiftcmd(int, char **); -int setcmd(int, char **); -int getoptscmd(int, char **); int nextopt(const char *); void getoptsreset(const char *); diff --git a/bin/sh/trap.c b/bin/sh/trap.c index aaa4753c7e5..2b6d8a585e4 100644 --- a/bin/sh/trap.c +++ b/bin/sh/trap.c @@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$"); #include "error.h" #include "trap.h" #include "mystring.h" +#include "builtins.h" #include "myhistedit.h" diff --git a/bin/sh/trap.h b/bin/sh/trap.h index d8686ceaadd..bf1250a85b8 100644 --- a/bin/sh/trap.h +++ b/bin/sh/trap.h @@ -37,7 +37,6 @@ extern int pendingsigs; extern int in_dotrap; extern volatile sig_atomic_t gotwinch; -int trapcmd(int, char **); void clear_traps(void); int have_traps(void); void setsignal(int); diff --git a/bin/sh/var.c b/bin/sh/var.c index e405b666ba7..d5b252230cb 100644 --- a/bin/sh/var.c +++ b/bin/sh/var.c @@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$"); #include "error.h" #include "mystring.h" #include "parser.h" +#include "builtins.h" #ifndef NO_HISTORY #include "myhistedit.h" #endif diff --git a/bin/sh/var.h b/bin/sh/var.h index f10bfcc7ad5..347c3777c36 100644 --- a/bin/sh/var.h +++ b/bin/sh/var.h @@ -123,11 +123,7 @@ void updatecharset(void); void initcharset(void); char **environment(void); int showvarscmd(int, char **); -int exportcmd(int, char **); -int localcmd(int, char **); void mklocal(char *); void poplocalvars(void); -int setvarcmd(int, char **); -int unsetcmd(int, char **); int unsetvar(const char *); int setvarsafe(const char *, const char *, int); diff --git a/contrib/gdb/gdb/ppcfbsd-tdep.c b/contrib/gdb/gdb/ppcfbsd-tdep.c index 3828e7f72b4..d8352246fa8 100644 --- a/contrib/gdb/gdb/ppcfbsd-tdep.c +++ b/contrib/gdb/gdb/ppcfbsd-tdep.c @@ -27,7 +27,9 @@ #include "target.h" #include "breakpoint.h" #include "value.h" +#include "gdb_string.h" #include "osabi.h" +#include "regset.h" #include "ppc-tdep.h" #include "ppcfbsd-tdep.h" @@ -80,6 +82,17 @@ ppcfbsd_supply_reg (char *regs, int regno) regcache_raw_supply (current_regcache, PC_REGNUM, regs + REG_PC_OFFSET); } +static void +ppcfbsd_supply_gregset (const struct regset *regset, + struct regcache *regcache, + int regnum, void *gregs, size_t size) +{ + ppcfbsd_supply_reg (gregs, -1); +} + +static struct regset ppcfbsd_gregset = { + NULL, (void*)ppcfbsd_supply_gregset +}; void ppcfbsd_fill_reg (char *regs, int regno) @@ -144,6 +157,20 @@ ppcfbsd_supply_fpreg (char *fpregs, int regno) fpregs + FPREG_FPSCR_OFFSET); } +static void +ppcfbsd_supply_fpregset (const struct regset *regset, + struct regcache * regcache, + int regnum, void *fpset, size_t size) +{ + ppcfbsd_supply_fpreg (fpset, -1); +} + + +static struct regset ppcfbsd_fpregset = +{ + NULL, (void*)ppcfbsd_supply_fpregset +}; + void ppcfbsd_fill_fpreg (char *fpregs, int regno) { @@ -174,69 +201,285 @@ ppcfbsd_fill_fpreg (char *fpregs, int regno) fpregs + FPREG_FPSCR_OFFSET); } -static void -fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which, - CORE_ADDR ignore) +/* Return the appropriate register set for the core section identified + by SECT_NAME and SECT_SIZE. */ + +const struct regset * +ppcfbsd_regset_from_core_section (struct gdbarch *gdbarch, + const char *sect_name, size_t sect_size) { - char *regs, *fpregs; + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - /* We get everything from one section. */ - if (which != 0) - return; + if (strcmp (sect_name, ".reg") == 0 && sect_size >= SIZEOF_STRUCT_REG) + return &ppcfbsd_gregset; - regs = core_reg_sect; - fpregs = core_reg_sect + SIZEOF_STRUCT_REG; + if (strcmp (sect_name, ".reg2") == 0 && sect_size >= SIZEOF_STRUCT_FPREG) + return &ppcfbsd_fpregset; - /* Integer registers. */ - ppcfbsd_supply_reg (regs, -1); - - /* Floating point registers. */ - ppcfbsd_supply_fpreg (fpregs, -1); + return NULL; } -static void -fetch_elfcore_registers (char *core_reg_sect, unsigned core_reg_size, int which, - CORE_ADDR ignore) + +/* Macros for matching instructions. Note that, since all the + operands are masked off before they're or-ed into the instruction, + you can use -1 to make masks. */ + +#define insn_d(opcd, rts, ra, d) \ + ((((opcd) & 0x3f) << 26) \ + | (((rts) & 0x1f) << 21) \ + | (((ra) & 0x1f) << 16) \ + | ((d) & 0xffff)) + +#define insn_ds(opcd, rts, ra, d, xo) \ + ((((opcd) & 0x3f) << 26) \ + | (((rts) & 0x1f) << 21) \ + | (((ra) & 0x1f) << 16) \ + | ((d) & 0xfffc) \ + | ((xo) & 0x3)) + +#define insn_xfx(opcd, rts, spr, xo) \ + ((((opcd) & 0x3f) << 26) \ + | (((rts) & 0x1f) << 21) \ + | (((spr) & 0x1f) << 16) \ + | (((spr) & 0x3e0) << 6) \ + | (((xo) & 0x3ff) << 1)) + +/* Read a PPC instruction from memory. PPC instructions are always + big-endian, no matter what endianness the program is running in, so + we can't use read_memory_integer or one of its friends here. */ +static unsigned int +read_insn (CORE_ADDR pc) { - switch (which) + unsigned char buf[4]; + + read_memory (pc, buf, 4); + return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; +} + + +/* An instruction to match. */ +struct insn_pattern +{ + unsigned int mask; /* mask the insn with this... */ + unsigned int data; /* ...and see if it matches this. */ + int optional; /* If non-zero, this insn may be absent. */ +}; + +/* Return non-zero if the instructions at PC match the series + described in PATTERN, or zero otherwise. PATTERN is an array of + 'struct insn_pattern' objects, terminated by an entry whose mask is + zero. + + When the match is successful, fill INSN[i] with what PATTERN[i] + matched. If PATTERN[i] is optional, and the instruction wasn't + present, set INSN[i] to 0 (which is not a valid PPC instruction). + INSN should have as many elements as PATTERN. Note that, if + PATTERN contains optional instructions which aren't present in + memory, then INSN will have holes, so INSN[i] isn't necessarily the + i'th instruction in memory. */ +static int +insns_match_pattern (CORE_ADDR pc, + struct insn_pattern *pattern, + unsigned int *insn) +{ + int i; + + for (i = 0; pattern[i].mask; i++) { - case 0: /* Integer registers. */ - if (core_reg_size != SIZEOF_STRUCT_REG) - warning (_("Wrong size register set in core file.")); + insn[i] = read_insn (pc); + if ((insn[i] & pattern[i].mask) == pattern[i].data) + pc += 4; + else if (pattern[i].optional) + insn[i] = 0; else - ppcfbsd_supply_reg (core_reg_sect, -1); - break; - - case 2: /* Floating point registers. */ - if (core_reg_size != SIZEOF_STRUCT_FPREG) - warning (_("Wrong size FP register set in core file.")); - else - ppcfbsd_supply_fpreg (core_reg_sect, -1); - break; - - default: - /* Don't know what kind of register request this is; just ignore it. */ - break; + return 0; } + + return 1; } -static struct core_fns ppcfbsd_core_fns = -{ - bfd_target_unknown_flavour, /* core_flavour */ - default_check_format, /* check_format */ - default_core_sniffer, /* core_sniffer */ - fetch_core_registers, /* core_read_registers */ - NULL /* next */ -}; -static struct core_fns ppcfbsd_elfcore_fns = +/* Return the 'd' field of the d-form instruction INSN, properly + sign-extended. */ +static CORE_ADDR +insn_d_field (unsigned int insn) { - bfd_target_elf_flavour, /* core_flavour */ - default_check_format, /* check_format */ - default_core_sniffer, /* core_sniffer */ - fetch_elfcore_registers, /* core_read_registers */ - NULL /* next */ -}; + return ((((CORE_ADDR) insn & 0xffff) ^ 0x8000) - 0x8000); +} + + +/* Return the 'ds' field of the ds-form instruction INSN, with the two + zero bits concatenated at the right, and properly + sign-extended. */ +static CORE_ADDR +insn_ds_field (unsigned int insn) +{ + return ((((CORE_ADDR) insn & 0xfffc) ^ 0x8000) - 0x8000); +} + + +/* If DESC is the address of a 64-bit PowerPC FreeBSD function + descriptor, return the descriptor's entry point. */ +static CORE_ADDR +ppc64_desc_entry_point (CORE_ADDR desc) +{ + /* The first word of the descriptor is the entry point. */ + return (CORE_ADDR) read_memory_unsigned_integer (desc, 8); +} + + +/* Pattern for the standard linkage function. These are built by + build_plt_stub in elf64-ppc.c, whose GLINK argument is always + zero. */ +static struct insn_pattern ppc64_standard_linkage[] = + { + /* addis r12, r2, */ + { insn_d (-1, -1, -1, 0), insn_d (15, 12, 2, 0), 0 }, + + /* std r2, 40(r1) */ + { -1, insn_ds (62, 2, 1, 40, 0), 0 }, + + /* ld r11, (r12) */ + { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 11, 12, 0, 0), 0 }, + + /* addis r12, r12, 1 */ + { insn_d (-1, -1, -1, -1), insn_d (15, 12, 2, 1), 1 }, + + /* ld r2, (r12) */ + { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 2, 12, 0, 0), 0 }, + + /* addis r12, r12, 1 */ + { insn_d (-1, -1, -1, -1), insn_d (15, 12, 2, 1), 1 }, + + /* mtctr r11 */ + { insn_xfx (-1, -1, -1, -1), insn_xfx (31, 11, 9, 467), + 0 }, + + /* ld r11, (r12) */ + { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 11, 12, 0, 0), 0 }, + + /* bctr */ + { -1, 0x4e800420, 0 }, + + { 0, 0, 0 } + }; +#define PPC64_STANDARD_LINKAGE_LEN \ + (sizeof (ppc64_standard_linkage) / sizeof (ppc64_standard_linkage[0])) + +/* When the dynamic linker is doing lazy symbol resolution, the first + call to a function in another object will go like this: + + - The user's function calls the linkage function: + + 100007c4: 4b ff fc d5 bl 10000498 + 100007c8: e8 41 00 28 ld r2,40(r1) + + - The linkage function loads the entry point (and other stuff) from + the function descriptor in the PLT, and jumps to it: + + 10000498: 3d 82 00 00 addis r12,r2,0 + 1000049c: f8 41 00 28 std r2,40(r1) + 100004a0: e9 6c 80 98 ld r11,-32616(r12) + 100004a4: e8 4c 80 a0 ld r2,-32608(r12) + 100004a8: 7d 69 03 a6 mtctr r11 + 100004ac: e9 6c 80 a8 ld r11,-32600(r12) + 100004b0: 4e 80 04 20 bctr + + - But since this is the first time that PLT entry has been used, it + sends control to its glink entry. That loads the number of the + PLT entry and jumps to the common glink0 code: + + 10000c98: 38 00 00 00 li r0,0 + 10000c9c: 4b ff ff dc b 10000c78 + + - The common glink0 code then transfers control to the dynamic + linker's fixup code: + + 10000c78: e8 41 00 28 ld r2,40(r1) + 10000c7c: 3d 82 00 00 addis r12,r2,0 + 10000c80: e9 6c 80 80 ld r11,-32640(r12) + 10000c84: e8 4c 80 88 ld r2,-32632(r12) + 10000c88: 7d 69 03 a6 mtctr r11 + 10000c8c: e9 6c 80 90 ld r11,-32624(r12) + 10000c90: 4e 80 04 20 bctr + + Eventually, this code will figure out how to skip all of this, + including the dynamic linker. At the moment, we just get through + the linkage function. */ + +/* If the current thread is about to execute a series of instructions + at PC matching the ppc64_standard_linkage pattern, and INSN is the result + from that pattern match, return the code address to which the + standard linkage function will send them. (This doesn't deal with + dynamic linker lazy symbol resolution stubs.) */ +static CORE_ADDR +ppc64_standard_linkage_target (CORE_ADDR pc, unsigned int *insn) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + + /* The address of the function descriptor this linkage function + references. */ + CORE_ADDR desc + = ((CORE_ADDR) read_register (tdep->ppc_gp0_regnum + 2) + + (insn_d_field (insn[0]) << 16) + + insn_ds_field (insn[2])); + + /* The first word of the descriptor is the entry point. Return that. */ + return ppc64_desc_entry_point (desc); +} + + +/* Given that we've begun executing a call trampoline at PC, return + the entry point of the function the trampoline will go to. */ +static CORE_ADDR +ppc64_skip_trampoline_code (CORE_ADDR pc) +{ + unsigned int ppc64_standard_linkage_insn[PPC64_STANDARD_LINKAGE_LEN]; + + if (insns_match_pattern (pc, ppc64_standard_linkage, + ppc64_standard_linkage_insn)) + return ppc64_standard_linkage_target (pc, ppc64_standard_linkage_insn); + else + return 0; +} + + +/* Support for CONVERT_FROM_FUNC_PTR_ADDR (ARCH, ADDR, TARG) on PPC64 + GNU/Linux and FreeBSD. + + Usually a function pointer's representation is simply the address + of the function. On GNU/Linux on the 64-bit PowerPC however, a + function pointer is represented by a pointer to a TOC entry. This + TOC entry contains three words, the first word is the address of + the function, the second word is the TOC pointer (r2), and the + third word is the static chain value. Throughout GDB it is + currently assumed that a function pointer contains the address of + the function, which is not easy to fix. In addition, the + conversion of a function address to a function pointer would + require allocation of a TOC entry in the inferior's memory space, + with all its drawbacks. To be able to call C++ virtual methods in + the inferior (which are called via function pointers), + find_function_addr uses this function to get the function address + from a function pointer. */ + +/* If ADDR points at what is clearly a function descriptor, transform + it into the address of the corresponding function. Be + conservative, otherwize GDB will do the transformation on any + random addresses such as occures when there is no symbol table. */ + +static CORE_ADDR +ppc64_fbsd_convert_from_func_ptr_addr (struct gdbarch *gdbarch, + CORE_ADDR addr, + struct target_ops *targ) +{ + struct section_table *s = target_section_by_addr (targ, addr); + + /* Check if ADDR points to a function descriptor. */ + if (s && strcmp (s->the_bfd_section->name, ".opd") == 0) + return get_target_memory_unsigned (targ, addr, 8); + + return addr; +} static int ppcfbsd_pc_in_sigtramp (CORE_ADDR pc, char *func_name) @@ -270,27 +513,42 @@ static void ppcfbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* FreeBSD doesn't support the 128-bit `long double' from the psABI. */ + set_gdbarch_long_double_bit (gdbarch, 64); + set_gdbarch_pc_in_sigtramp (gdbarch, ppcfbsd_pc_in_sigtramp); - /* For NetBSD, this is an on again, off again thing. Some systems - do use the broken struct convention, and some don't. */ - set_gdbarch_return_value (gdbarch, ppcfbsd_return_value); -#ifdef __powerpc64__ - set_solib_svr4_fetch_link_map_offsets (gdbarch, - svr4_lp64_fetch_link_map_offsets); -#else - set_solib_svr4_fetch_link_map_offsets (gdbarch, - svr4_ilp32_fetch_link_map_offsets); -#endif + + if (tdep->wordsize == 4) + { + set_gdbarch_return_value (gdbarch, ppcfbsd_return_value); + set_solib_svr4_fetch_link_map_offsets (gdbarch, + svr4_ilp32_fetch_link_map_offsets); + } + + if (tdep->wordsize == 8) + { + set_gdbarch_convert_from_func_ptr_addr + (gdbarch, ppc64_fbsd_convert_from_func_ptr_addr); + + set_gdbarch_skip_trampoline_code (gdbarch, ppc64_skip_trampoline_code); + + set_solib_svr4_fetch_link_map_offsets (gdbarch, + svr4_lp64_fetch_link_map_offsets); + } + + set_gdbarch_regset_from_core_section (gdbarch, + ppcfbsd_regset_from_core_section); } void _initialize_ppcfbsd_tdep (void) { + gdbarch_register_osabi (bfd_arch_powerpc, bfd_mach_ppc, + GDB_OSABI_FREEBSD_ELF, ppcfbsd_init_abi); + gdbarch_register_osabi (bfd_arch_powerpc, bfd_mach_ppc64, + GDB_OSABI_FREEBSD_ELF, ppcfbsd_init_abi); gdbarch_register_osabi (bfd_arch_rs6000, 0, GDB_OSABI_FREEBSD_ELF, ppcfbsd_init_abi); - gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_FREEBSD_ELF, - ppcfbsd_init_abi); - - add_core_fns (&ppcfbsd_core_fns); - add_core_fns (&ppcfbsd_elfcore_fns); } diff --git a/contrib/pf/pfctl/pfctl.8 b/contrib/pf/pfctl/pfctl.8 index 24be6e51c48..917a859745c 100644 --- a/contrib/pf/pfctl/pfctl.8 +++ b/contrib/pf/pfctl/pfctl.8 @@ -26,7 +26,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 20, 2002 +.Dd June 13, 2011 .Dt PFCTL 8 .Os .Sh NAME @@ -35,7 +35,7 @@ .Sh SYNOPSIS .Nm pfctl .Bk -words -.Op Fl AdeghmNnOqRrvz +.Op Fl AdeghmNnOPqRrvz .Op Fl a Ar anchor .Oo Fl D Ar macro Ns = .Ar value Oc @@ -350,6 +350,9 @@ without any options will enable optimizations, and a second .Fl o will enable profiling. +.It Fl P +Do not perform service name lookup for port specific rules, +instead display the ports numerically. .It Fl p Ar device Use the device file .Ar device @@ -670,6 +673,7 @@ Passive operating system fingerprint database. .Xr pf.conf 5 , .Xr pf.os 5 , .Xr rc.conf 5 , +.Xr services 5 , .Xr sysctl.conf 5 , .Xr authpf 8 , .Xr ftp-proxy 8 , diff --git a/contrib/pf/pfctl/pfctl.c b/contrib/pf/pfctl/pfctl.c index 21995f6468d..e76261bdcbb 100644 --- a/contrib/pf/pfctl/pfctl.c +++ b/contrib/pf/pfctl/pfctl.c @@ -235,7 +235,7 @@ usage(void) { extern char *__progname; - fprintf(stderr, "usage: %s [-AdeghmNnOqRrvz] ", __progname); + fprintf(stderr, "usage: %s [-AdeghmNnOPqRrvz] ", __progname); fprintf(stderr, "[-a anchor] [-D macro=value] [-F modifier]\n"); fprintf(stderr, "\t[-f file] [-i interface] [-K host | network] "); fprintf(stderr, "[-k host | network ]\n"); @@ -770,6 +770,7 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, struct pfioc_rule pr; u_int32_t nr, mnr, header = 0; int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG); + int numeric = opts & PF_OPT_NUMERIC; int len = strlen(path); int brace; char *p; @@ -834,7 +835,7 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, case PFCTL_SHOW_RULES: if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL)) labels = 1; - print_rule(&pr.rule, pr.anchor_call, rule_numbers); + print_rule(&pr.rule, pr.anchor_call, rule_numbers, numeric); printf("\n"); pfctl_print_rule_counters(&pr.rule, opts); break; @@ -894,7 +895,7 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format, } else p = &pr.anchor_call[0]; - print_rule(&pr.rule, p, rule_numbers); + print_rule(&pr.rule, p, rule_numbers, numeric); if (brace) printf(" {\n"); else @@ -951,7 +952,7 @@ pfctl_show_nat(int dev, int opts, char *anchorname) dotitle = 0; } print_rule(&pr.rule, pr.anchor_call, - opts & PF_OPT_VERBOSE2); + opts & PF_OPT_VERBOSE2, opts & PF_OPT_NUMERIC); printf("\n"); pfctl_print_rule_counters(&pr.rule, opts); pfctl_clear_pool(&pr.rule.rpool); @@ -1318,7 +1319,8 @@ pfctl_load_rule(struct pfctl *pf, char *path, struct pf_rule *r, int depth) if (pf->opts & PF_OPT_VERBOSE) { INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2)); print_rule(r, r->anchor ? r->anchor->name : "", - pf->opts & PF_OPT_VERBOSE2); + pf->opts & PF_OPT_VERBOSE2, + pf->opts & PF_OPT_NUMERIC); } path[len] = '\0'; pfctl_clear_pool(&r->rpool); @@ -1978,7 +1980,7 @@ main(int argc, char *argv[]) usage(); while ((ch = getopt(argc, argv, - "a:AdD:eqf:F:ghi:k:K:mnNOo::p:rRs:t:T:vx:z")) != -1) { + "a:AdD:eqf:F:ghi:k:K:mnNOo::Pp:rRs:t:T:vx:z")) != -1) { switch (ch) { case 'a': anchoropt = optarg; @@ -2080,6 +2082,9 @@ main(int argc, char *argv[]) case 'p': pf_device = optarg; break; + case 'P': + opts |= PF_OPT_NUMERIC; + break; case 's': showopt = pfctl_lookup_option(optarg, showopt_list); if (showopt == NULL) { diff --git a/contrib/pf/pfctl/pfctl_optimize.c b/contrib/pf/pfctl/pfctl_optimize.c index 44c04779d61..0514e8105bf 100644 --- a/contrib/pf/pfctl/pfctl_optimize.c +++ b/contrib/pf/pfctl/pfctl_optimize.c @@ -407,7 +407,7 @@ optimize_superblock(struct pfctl *pf, struct superblock *block) TAILQ_FOREACH(por, &block->sb_rules, por_entry) { printf(" "); print_rule(&por->por_rule, por->por_rule.anchor ? - por->por_rule.anchor->name : "", 1); + por->por_rule.anchor->name : "", 1, 0); } #endif /* OPT_DEBUG */ diff --git a/contrib/pf/pfctl/pfctl_parser.c b/contrib/pf/pfctl/pfctl_parser.c index c9b2e1189b6..7dc0c592f2e 100644 --- a/contrib/pf/pfctl/pfctl_parser.c +++ b/contrib/pf/pfctl/pfctl_parser.c @@ -64,11 +64,11 @@ __FBSDID("$FreeBSD$"); #include "pfctl.h" void print_op (u_int8_t, const char *, const char *); -void print_port (u_int8_t, u_int16_t, u_int16_t, const char *); +void print_port (u_int8_t, u_int16_t, u_int16_t, const char *, int); void print_ugid (u_int8_t, unsigned, unsigned, const char *, unsigned); void print_flags (u_int8_t); void print_fromto(struct pf_rule_addr *, pf_osfp_t, - struct pf_rule_addr *, u_int8_t, u_int8_t, int); + struct pf_rule_addr *, u_int8_t, u_int8_t, int, int); int ifa_skip_if(const char *filter, struct node_host *p); struct node_host *ifa_grouplookup(const char *, int); @@ -320,12 +320,15 @@ print_op(u_int8_t op, const char *a1, const char *a2) } void -print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, const char *proto) +print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, const char *proto, int numeric) { char a1[6], a2[6]; struct servent *s; - s = getservbyport(p1, proto); + if (!numeric) + s = getservbyport(p1, proto); + else + s = NULL; p1 = ntohs(p1); p2 = ntohs(p2); snprintf(a1, sizeof(a1), "%u", p1); @@ -363,7 +366,7 @@ print_flags(u_int8_t f) void print_fromto(struct pf_rule_addr *src, pf_osfp_t osfp, struct pf_rule_addr *dst, - sa_family_t af, u_int8_t proto, int verbose) + sa_family_t af, u_int8_t proto, int verbose, int numeric) { char buf[PF_OSFP_LEN*3]; if (src->addr.type == PF_ADDR_ADDRMASK && @@ -384,7 +387,8 @@ print_fromto(struct pf_rule_addr *src, pf_osfp_t osfp, struct pf_rule_addr *dst, if (src->port_op) print_port(src->port_op, src->port[0], src->port[1], - proto == IPPROTO_TCP ? "tcp" : "udp"); + proto == IPPROTO_TCP ? "tcp" : "udp", + numeric); if (osfp != PF_OSFP_ANY) printf(" os \"%s\"", pfctl_lookup_fingerprint(osfp, buf, sizeof(buf))); @@ -396,7 +400,8 @@ print_fromto(struct pf_rule_addr *src, pf_osfp_t osfp, struct pf_rule_addr *dst, if (dst->port_op) print_port(dst->port_op, dst->port[0], dst->port[1], - proto == IPPROTO_TCP ? "tcp" : "udp"); + proto == IPPROTO_TCP ? "tcp" : "udp", + numeric); } } @@ -673,7 +678,7 @@ print_src_node(struct pf_src_node *sn, int opts) } void -print_rule(struct pf_rule *r, const char *anchor_call, int verbose) +print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int numeric) { static const char *actiontypes[] = { "pass", "block", "scrub", "no scrub", "nat", "no nat", "binat", "no binat", "rdr", "no rdr" }; @@ -800,7 +805,7 @@ print_rule(struct pf_rule *r, const char *anchor_call, int verbose) printf(" proto %u", r->proto); } print_fromto(&r->src, r->os_fingerprint, &r->dst, r->af, r->proto, - verbose); + verbose, numeric); if (r->uid.op) print_ugid(r->uid.op, r->uid.uid[0], r->uid.uid[1], "user", UID_MAX); diff --git a/contrib/pf/pfctl/pfctl_parser.h b/contrib/pf/pfctl/pfctl_parser.h index 4885203a532..ab9017e51a2 100644 --- a/contrib/pf/pfctl/pfctl_parser.h +++ b/contrib/pf/pfctl/pfctl_parser.h @@ -48,6 +48,7 @@ #define PF_OPT_DEBUG 0x0200 #define PF_OPT_SHOWALL 0x0400 #define PF_OPT_OPTIMIZE 0x0800 +#define PF_OPT_NUMERIC 0x1000 #define PF_OPT_MERGE 0x2000 #define PF_OPT_RECURSE 0x4000 @@ -235,7 +236,7 @@ int pfctl_load_anchors(int, struct pfctl *, struct pfr_buffer *); void print_pool(struct pf_pool *, u_int16_t, u_int16_t, sa_family_t, int); void print_src_node(struct pf_src_node *, int); -void print_rule(struct pf_rule *, const char *, int); +void print_rule(struct pf_rule *, const char *, int, int); void print_tabledef(const char *, int, int, struct node_tinithead *); void print_status(struct pf_status *, int); diff --git a/contrib/sendmail/CACerts b/contrib/sendmail/CACerts index dee28194ebc..245148d8398 100644 --- a/contrib/sendmail/CACerts +++ b/contrib/sendmail/CACerts @@ -1,4 +1,4 @@ -# $Id: CACerts,v 8.4 2009/06/26 05:46:10 ca Exp $ +# $Id: CACerts,v 8.5 2011/05/06 23:05:10 ca Exp $ # This file contains some CA certificates that are used to sign the # certificates of mail servers of members of the sendmail consortium # who may reply to questions etc sent to sendmail.org. @@ -6,73 +6,6 @@ # a certificate signed by one of these CA certificates. # -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 0 (0x0) - Signature Algorithm: md5WithRSAEncryption - Issuer: C=US, ST=Illinois, L=De Kalb, O=Northern Illinois University, OU=Computer Science, CN=Neil Rickert/emailAddress=rickert@cs.niu.edu - Validity - Not Before: May 12 00:40:50 2000 GMT - Not After : May 20 00:40:50 2010 GMT - Subject: C=US, ST=Illinois, L=De Kalb, O=Northern Illinois University, OU=Computer Science, CN=Neil Rickert/emailAddress=rickert@cs.niu.edu - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - RSA Public Key: (1024 bit) - Modulus (1024 bit): - 00:b1:1b:49:06:ef:3f:44:e0:93:ad:8c:a7:f7:21: - 7c:87:cb:da:35:f6:4b:a2:fd:8a:a0:07:5b:cc:6a: - 9b:89:33:fc:24:f5:b1:24:59:5a:25:50:fd:16:d7: - d4:bc:c7:04:1d:df:90:9b:5e:c3:a8:e9:8b:7d:a3: - 5d:9a:e9:7f:e5:2b:ea:15:a7:ad:ba:58:26:0a:11: - 49:4f:da:9a:67:7f:b0:a6:66:f4:27:b6:61:4e:3c: - c8:3e:a0:2f:6a:b4:0e:15:d6:39:f8:92:60:85:df: - a6:34:f3:fa:a4:a5:e4:47:49:e7:87:a4:a5:5c:8e: - 6a:2f:13:76:5f:29:f3:64:73 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Subject Key Identifier: - B6:31:78:BB:7E:AA:4D:A1:5D:FD:A2:24:18:C6:90:5A:2D:2F:19:48 - X509v3 Authority Key Identifier: - keyid:B6:31:78:BB:7E:AA:4D:A1:5D:FD:A2:24:18:C6:90:5A:2D:2F:19:48 - DirName:/C=US/ST=Illinois/L=De Kalb/O=Northern Illinois University/OU=Computer Science/CN=Neil Rickert/emailAddress=rickert@cs.niu.edu - serial:00 - - X509v3 Basic Constraints: - CA:TRUE - Signature Algorithm: md5WithRSAEncryption - 60:69:23:65:97:51:5c:06:a4:42:cb:00:e7:9a:dc:39:70:c3: - d3:5d:bf:0f:e0:04:54:4d:d9:dc:12:57:12:6c:67:fd:5b:b0: - 39:63:ea:c4:12:65:51:bb:3d:f1:f7:25:b4:cd:0b:f6:5b:7a: - 61:25:ad:06:0a:01:55:dc:71:05:29:0d:73:e9:30:51:be:d3: - e1:b2:89:fc:0f:28:f7:06:75:96:1b:34:75:e0:07:e5:3b:b3: - 0b:28:24:e5:79:ea:55:39:e7:d2:ee:ec:63:b4:e4:c6:ee:cb: - 15:d0:c8:eb:3b:4f:36:10:a4:6a:c0:6b:03:e8:29:72:c7:a7: - 10:00 ------BEGIN CERTIFICATE----- -MIID5TCCA06gAwIBAgIBADANBgkqhkiG9w0BAQQFADCBrjELMAkGA1UEBhMCVVMx -ETAPBgNVBAgTCElsbGlub2lzMRAwDgYDVQQHEwdEZSBLYWxiMSUwIwYDVQQKExxO -b3J0aGVybiBJbGxpbm9pcyBVbml2ZXJzaXR5MRkwFwYDVQQLExBDb21wdXRlciBT -Y2llbmNlMRUwEwYDVQQDEwxOZWlsIFJpY2tlcnQxITAfBgkqhkiG9w0BCQEWEnJp -Y2tlcnRAY3Mubml1LmVkdTAeFw0wMDA1MTIwMDQwNTBaFw0xMDA1MjAwMDQwNTBa -MIGuMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0Rl -IEthbGIxJTAjBgNVBAoTHE5vcnRoZXJuIElsbGlub2lzIFVuaXZlcnNpdHkxGTAX -BgNVBAsTEENvbXB1dGVyIFNjaWVuY2UxFTATBgNVBAMTDE5laWwgUmlja2VydDEh -MB8GCSqGSIb3DQEJARYScmlja2VydEBjcy5uaXUuZWR1MIGfMA0GCSqGSIb3DQEB -AQUAA4GNADCBiQKBgQCxG0kG7z9E4JOtjKf3IXyHy9o19kui/YqgB1vMapuJM/wk -9bEkWVolUP0W19S8xwQd35CbXsOo6Yt9o12a6X/lK+oVp626WCYKEUlP2ppnf7Cm -ZvQntmFOPMg+oC9qtA4V1jn4kmCF36Y08/qkpeRHSeeHpKVcjmovE3ZfKfNkcwID -AQABo4IBDzCCAQswHQYDVR0OBBYEFLYxeLt+qk2hXf2iJBjGkFotLxlIMIHbBgNV -HSMEgdMwgdCAFLYxeLt+qk2hXf2iJBjGkFotLxlIoYG0pIGxMIGuMQswCQYDVQQG -EwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0RlIEthbGIxJTAjBgNV -BAoTHE5vcnRoZXJuIElsbGlub2lzIFVuaXZlcnNpdHkxGTAXBgNVBAsTEENvbXB1 -dGVyIFNjaWVuY2UxFTATBgNVBAMTDE5laWwgUmlja2VydDEhMB8GCSqGSIb3DQEJ -ARYScmlja2VydEBjcy5uaXUuZWR1ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcN -AQEEBQADgYEAYGkjZZdRXAakQssA55rcOXDD012/D+AEVE3Z3BJXEmxn/VuwOWPq -xBJlUbs98fcltM0L9lt6YSWtBgoBVdxxBSkNc+kwUb7T4bKJ/A8o9wZ1lhs0deAH -5TuzCygk5XnqVTnn0u7sY7Tkxu7LFdDI6ztPNhCkasBrA+gpcsenEAA= ------END CERTIFICATE----- - Certificate: Data: Version: 3 (0x2) diff --git a/contrib/sendmail/FREEBSD-upgrade b/contrib/sendmail/FREEBSD-upgrade index 5d4cf6512e9..cabeb2eadbb 100644 --- a/contrib/sendmail/FREEBSD-upgrade +++ b/contrib/sendmail/FREEBSD-upgrade @@ -1,6 +1,6 @@ $FreeBSD$ -sendmail 8.14.4 +sendmail 8.14.5 originals can be found at: ftp://ftp.sendmail.org/pub/sendmail/ For the import of sendmail, the following directories were renamed: @@ -110,4 +110,4 @@ infrastructure in FreeBSD: usr.sbin/mailwrapper/Makefile gshapiro@FreeBSD.org -25-January-2010 +13-June-2011 diff --git a/contrib/sendmail/KNOWNBUGS b/contrib/sendmail/KNOWNBUGS index 998fb11c7e5..5b7918cef55 100644 --- a/contrib/sendmail/KNOWNBUGS +++ b/contrib/sendmail/KNOWNBUGS @@ -12,6 +12,14 @@ distribution). This list is not guaranteed to be complete. +* Header values which are too long may be truncated. + + If a value of a structured header is longer than 256 (MAXNAME) + characters then it may be truncated during output. For example, + if a single address in the To: header is longer than 256 characters + then it will be truncated which may result in a syntactically + invalid address. + * Delivery to programs that generate too much output may cause problems If e-mail is delivered to a program which generates too much @@ -258,4 +266,4 @@ Kresolve sequence dnsmx canon be used if set instead of LOCAL_RELAY ($R). This will be fixed in a future version. -$Revision: 8.60 $, Last updated $Date: 2007/12/04 01:16:50 $ +$Revision: 8.61 $, Last updated $Date: 2011/04/07 17:48:23 $ diff --git a/contrib/sendmail/LICENSE b/contrib/sendmail/LICENSE index 2c604033ee3..a0ad12472c4 100644 --- a/contrib/sendmail/LICENSE +++ b/contrib/sendmail/LICENSE @@ -1,8 +1,9 @@ SENDMAIL LICENSE -The following license terms and conditions apply, unless a different -license is obtained from Sendmail, Inc., 6475 Christie Ave, Suite 350, -Emeryville, CA 94608, USA, or by electronic mail at license@sendmail.com. +The following license terms and conditions apply, unless a redistribution +agreement or other license is obtained from Sendmail, Inc., 6475 Christie +Ave, Third Floor, Emeryville, CA 94608, USA, or by electronic mail at +license@sendmail.com. License Terms: @@ -22,10 +23,11 @@ each of the following conditions is met: must allow further use, modification, and redistribution of the Source Code under substantially the same terms as this license. For the purposes of redistribution "Source Code" means the complete compilable - and linkable source code of sendmail including all modifications. + and linkable source code of sendmail and associated libraries and + utilities in the sendmail distribution including all modifications. -2. Redistributions of source code must retain the copyright notices as they - appear in each source code file, these license terms, and the +2. Redistributions of Source Code must retain the copyright notices as they + appear in each Source Code file, these license terms, and the disclaimer/limitation of liability set forth as paragraph 6 below. 3. Redistributions in binary form must reproduce the Copyright Notice, @@ -33,16 +35,16 @@ each of the following conditions is met: forth as paragraph 6 below, in the documentation and/or other materials provided with the distribution. For the purposes of binary distribution the "Copyright Notice" refers to the following language: - "Copyright (c) 1998-2009 Sendmail, Inc. All rights reserved." + "Copyright (c) 1998-2010 Sendmail, Inc. All rights reserved." 4. Neither the name of Sendmail, Inc. nor the University of California nor - the names of their contributors may be used to endorse or promote + names of their contributors may be used to endorse or promote products derived from this software without specific prior written permission. The name "sendmail" is a trademark of Sendmail, Inc. 5. All redistributions must comply with the conditions imposed by the - University of California on certain embedded code, whose copyright - notice and conditions for redistribution are as follows: + University of California on certain embedded code, which copyright + Notice and conditions for redistribution are as follows: (a) Copyright (c) 1988, 1993 The Regents of the University of California. All rights reserved. @@ -76,4 +78,4 @@ each of the following conditions is met: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. -$Revision: 8.15 $, Last updated $Date: 2009/03/04 19:58:04 $ +$Revision: 8.17 $, Last updated $Date: 2010/12/03 01:10:00 $, Document 139848.1 diff --git a/contrib/sendmail/PGPKEYS b/contrib/sendmail/PGPKEYS index 5f89ed43942..fd6daf86ce1 100644 --- a/contrib/sendmail/PGPKEYS +++ b/contrib/sendmail/PGPKEYS @@ -141,6 +141,223 @@ gpExpdV7qPrw9k01j5rod5PjZlG8zV0= =SR28 -----END PGP PUBLIC KEY BLOCK----- +Type Bits KeyID Created Expires Algorithm Use +pub 2048 A97884B0 2011-01-04 ------- RSA Sign & Encrypt +fingerprint: 5872 6218 A913 400D E660 3601 39A4 C77D A978 84B0 +uid Sendmail Signing Key/2011 + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.9 (OpenBSD) + +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 +=pDAG +-----END PGP PUBLIC KEY BLOCK----- + +Type Bits KeyID Created Expires Algorithm Use +pub 2048 85410ABE 2010-02-19 ------- RSA Sign +fingerprint: B175 9644 5303 5DCE DD7B E919 604D FBF2 8541 0ABE +uid Sendmail Signing Key/2010 + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.9 (OpenBSD) + +mQENBEt+6goBCAC95sVPzf4AWFmUklHO9yGBq6K135Tlt9JaX3frj6PCBjkLNn97 +J5WDAoLqE9wB7WgiBzs2lu8OPZZcf+6syd97SojEze5bj2uv84DBv2juupbHEBys +9OH52QqYWG+1yuwAHY2gjKLYcvNgaOKLp5hoHZ2rakRc4a2ypLTPazsGFBO9/qBA ++v6qkP70/lOZeN9HX/yipbygAE+Y9elptW6ohvdGW8jbtllFqYFebB+lIaclkQnK +pldnQfktnJDB+XmLOc5m/1BsultlI5IH9HXCeskXxLcxXq+ldg+it1DgzxmHpHTK +dIhgOKY3MvTgxkcXiwIGcHBMnov6ESL1KaU5ABEBAAG0MVNlbmRtYWlsIFNpZ25p +bmcgS2V5LzIwMTAgPHNlbmRtYWlsQFNlbmRtYWlsLk9SRz6JATkEEwECACMFAkt+ +6goCGwMHCwkIBwMCAQYVCAIJCgsEFgIDAQIeAQIXgAAKCRBgTfvyhUEKvi4qB/0T +Em3whttGoUrxdZd1gYKI9SY1/4dHOhD+xJQQgIoQSRpOEA7xQ6TTAYvG8sYdsF5K +9/lWjOTEy5w6wBcu4e9F7aO/TUzue/7p0c2UKJTrEOw4HsRrENfQHx1TAXudQHHn +5+PgBCQCSr36ktuSXnlOo2bGbZ4FUwNCu0ztmoEEca8ZgY6ciEXbva1kRj6Eumul +MkqtVYEAtjzdIga6M3xYuJlus+qi/uEj5kivtf2LUDxXpGE6XFrArum0za/URiW8 +wxt5zBbTbne3tDr2yg6GC046+f1Wr02xWYapGyNRU6yrPciWOu0tpaxJ7CwEIMRq +6HzbSVdZkqOdSoZ3ufqYiJwEEAECAAYFAkt+6lkACgkQEolum6d/JClfWAP/VBVb +VYBQKV+NQyXl6ULJI91iIpEAR/T3nRoemGVPhbB8a7zRRkz1h4ou6VAMJeS4BxSC +fm2iOHCYMAOMSQ03VaEM2F13b8PtsGaKjuAwDf2pHARYbOj4DRCY0dUmwPXze3Tp +7S5ui/fk9t+NhQQa6IZHFkqdnQ+xZ88hhoF5slmInAQQAQIABgUCS37q1AAKCRDv +WJZk1DLhnTPYA/0VhRNooc2csxwvxBG6HiS8wp2k+kbGbbtlQ4JFg59p4EUnT2Ld +P9eUzFtj6fRkU/bZcIKgOn37M4GOXEoNvMT6NfmpTKeofg7hwp+pMdHlq4y9Em55 +TSC+rK2g6rAaSxMvDzasBouQqfxirj3nBI65zVHK98Zaj9vrpWCVCBIoZoicBBAB +AgAGBQJLfurtAAoJEG9Sk9ijm6ZVjcoEAJdB5kzFWHsvf0u/Oe+LWQwowL5SjQ6W +uhKgTDJ5IqFbDlCT/V33mpLEC9us4wNRT6Bff5agInCKfcUXdJijExkEbDB9ErZc +WmZqtquxQJN3xH+fIoIorxjWD0RMPmMvwQRgjn/puXwichQP9PafTgd9YsQ3aWAU +DGvx1U8pkloCiJwEEAECAAYFAkt+6vIACgkQnBy94uNcVjWGswQAhqDOQ8Os3gOo +UAGm/Oju6t6JG4wxLyl7vlMZ2eQHAX8rJ99Q4kyJB9xR4uaZ42BwbPx3s25N67qb +6z/ZAMrtqsXuK90+WlwykxG1uq4FOznHU6QT7cyO48Yeoq2PO1kFgQuRESPCRxXV +8dmDgeoDQ0EDO1Ykm003AKCd0N7+n1CInAQQAQIABgUCS37q9wAKCRA4IttHzDdP +LXmrA/4r9bzS6YnAHE0MFzByA2uZq0HeyrHI/Q6ELzqeMjuu/CwKdki/8gzz6Zt3 +KkXbqd9mPidsi/nqfUwQlqMHCFSRTyqw3FkGzQ/wk9fk4G+AF+5A//xGFIACHd54 +a/1+k0iVM5GNQkrknltYps0TmW8priU1uzmzAHpsCh0e4xFDIYicBBABAgAGBQJL +fur9AAoJEIlpYrhnjAoD9mQD/0s7tHTX+Mzt7iwZzsAZEqoxSQS5dUAKK+j6GR5K +8/cWcdiDJwCABViIn+TT7/GDmTlA4EUKQzIMPDfuagqa1SPxKXgivUnfhmpJVAma +MUmZeGFQyfTBjp4qZ+Agk15Ulnz7arqmOmeAWSvdsJ/vCm44TCEDO1gIjLzgyOIc +ktU5iJwEEAECAAYFAkt+6wQACgkQIYPhsTlvB4lH8wQAyqIKclShWxxaXi6YpS/k +H+susHMVePzBPyEmv93UkSOj2bdMWuhVENPXlBn1UnFt0vKPOL+krF3+zIAjg6N6 +zFlasBUL9p2HqRI35Sq4cn3S3Im4vZIPwWNYgtQY41Hc1Gx2pIxmKtIz+9+sUiTE +DGrTxnzUAohPaTzUVXPtWOuInAQQAQIABgUCS37rCgAKCRDI1e0plfYXcQXaA/9D ++sQJdEc1orgN/aTVGKkKoNyMmJhtNLECYIsfAYcE9lMGtymkkli0BrvrtNN1Co6P +qmR+oaZSmeyq0qNVdV8AnoyFI5Dk3Nir82ISOtvzuNzn8NrosSed0nyVmg88amTa +WoJS7as6s6/lCxuarGwRuHA7vXaxDg92lCYeTw09I4icBBABAgAGBQJLfusSAAoJ +EHCgJE0e+ZJRWiMD/i65FDmbZo0srV01XwSUb8EF/70RF0uOxrGfunMin93cR8VW +mNSzcydfH/mKR1Rf4Snsz9hp9NWryZpjVXrPJx6GOBzzwgyUtzAxH6OElv7rlK2Y +XJ+Xi94djsyB56e6PKHA1uB30g2l5beh0bDUEa9mLfstTidMWGXRdtnVtW5KiJwE +EAECAAYFAkt+6yAACgkQHnuzyK+VliU0OQQApyvdx0YKiDL7EuLf/QkOk64DRAKf +7rxZSlN5jHnNJSQeX7cMRBcklbl/GlZH2oyHdDuahrZ62MT/mCneRIH58lf8c91h +WLFjkpU/j8Md8ahFQDWpCwNSSwz4tqZyhKfeP/w0OaHC4ttAwbjKk6mn0wFpWxpH +sYFc08L5PoUyaQaInAQQAQIABgUCS37rJAAKCRCXQwEYcJO4QR+cA/9EEv5UJCgt +0glLmhIzpvGxlEyzhVqhtfDE8CI06lOSGWhYy4VCcOCho8ig+atxU1+/zPaJGIbI +mvR+kuPZ9kmtd+LtV6fWtp7U6FrAZSXV6paWHc9ZCLJeKSNwmRrcOqaBEjj3MqNA +pwXO3gCiuylHzgIo05+FxRho91AS/mciI4icBBABAgAGBQJLfusoAAoJENiq8Mr2 +swcppz4EALJ3JQOIPsvgptuPdq8XZuxxuFonjcr8RaLB89a9MDduFBM8zw/Q0qcA +asltDtQidMwn+VCDQavkrpEM2QbNxFfhbdnw5c97CvovgmTATPaR2XZ7LaeIwE36 +HLL5e5/k0BThiqymD3tjaFbx7uTK2o3ZTyMvbjtqMOdt0eLqFvHRiJwEEAECAAYF +Akt+6ywACgkQwCnKQBb0zOnn+AP+OdZu4BowBVYzmygmM1O7XyiEMd5TB3MxwkZR +8+rGW8Xcl4JtLY9iiXzfakTHuP3OrINrhXnMQLAY46kAcUc+VcHvLdMth6btsltE +Jjc33aZovPRabCeKVCnDKcEPRYclsXgGStXlFMoacI2KUUENZeGCUr0NJb7RnAk5 +Pfuib+mInAQQAQIABgUCS37rVgAKCRDBnB0lEtNGHcMMA/9mYtgCaK/zihws7d4V +p+uQXKjnfhKZx4XX33BoUFgxC2N5/TB6qd0sBnaUYby/DDGh6W3721dGTw66i9vF +Wn2IJ6JUj4CpLCCFVb9FxPdjrt/F1eKg8N1SOfVQg0D9Nkl48Y81tIf0xcMa9yuV +8qssX8baTDhatDGFIZlYPfGpZIicBBABAgAGBQJLg2FTAAoJEM8etQMiMnoByVwD +/3iim8IBm3ssOFJ58RR9wFPgH7INTiE28vO5yO+f2i0/cEdWwJDwmqOpKhUM7DWy +LeK7LaZWzViuxh83ZI2KlcJJksdFtohuzyJul/phyaQYDPGlgu7AIthNm49pdDnR +0AAQl98ccn0iT69Zp3Fi5fRMHVC4ChBsBir5JjJBh0aliJwEEAECAAYFAkuDdtQA +CgkQvdqP1j/qff0GMwQAqgbWFQsOoEzzwSDo/SEun8gmRRLUH8vWx5Us659x2nQy +BPtp8w2HpqKsyMn2E4TavKjyzUZPINziPVszXhG+dtCFuOQvRFFZzFQccdhAIB8o +KJ7y/LRa7MpvIMRFJOURBnJgQ3asUojRcksd+rgMqujFrwyYN5J+LeXwBXS9eMSI +nAQQAQIABgUCS4N2+gAKCRB8S2dtoA4VY6KoA/91U29DqRR0XRlk+KdRs6Qjo/R0 +lQp7uUtuP55xJkv+UMPVhABbMOR+/sjE8eUJdMpHfaQmdG89M5VZ+Ck2MZrhjveE +acNH/sIWCDvIFV5gheNZycpp+wH2VO7+i9bWmMVl4JKK0grFRYQMqiqT+tHYfXS3 +MVQH8U4EhwnFuwFrgoicBBABAgAGBQJLg3cQAAoJENbgof5PvirdPboD/jUU/UV7 +7jGtnW9+xrsUUDcHeU8Ha/VKXfKts4Z0KifWYnjUOH5jR/OqYzHy7vAOyGpyrziN +eJHLM/I8AuTtmsCY3IpfhaeRg4ZkJYRqx5QkhfUesOpPfKVPYtoF53Uw04iu0dtv +2bFftaX0tX/hKhWmzobllBGM9b5E4G+kHCRZiEYEEBECAAYFAkuEoagACgkQCaei +StHlggfktQCgjyKOB4tlm9WnufcJaYIbchyZVSQAn3thzs5akheaVsVwBHSmpJyk +PDRbiJwEEAECAAYFAkuFS4UACgkQXx7Ib4gMnlUZEQP9HoutmYz6pAB8XEADTKrR +wTWGqu/S4V6zhSJbIYSDIFAY+WeKCTUdVO8eFfrPIrS459z8yQ3PgFKL3QMp1VgX +jMGPcvfHOjWh1jSw5W1aLcJX428T0oybgLZLvPT7QXpIwKcY8TtS/jjVTaepIqIG +9tmQupstoaw/h9b1vHY7R7uIRgQQEQIABgUCS4Uc9QAKCRCWnNphS7Y2SyT5AKCE +1AR60B2GDZ75U2kaNe/SyOQJ3ACfVtndQ22edDOB1INak6SyfYv9ZuSIRgQQEQIA +BgUCS4TumQAKCRCiu/skDPlW9we5AKC6dNVZjpg/yDQiepI2E0XZ222vzACeJ7Ds +41t2z3BT4qGJyZrpGK8G3kKIRgQQEQIABgUCS4TuuQAKCRD7VAFa+haI7WniAKCY +mNr9FG/180EcUY/tgaHNuUDXtwCfX0DYjxL9ExvQ7wB2uXB2M7AwGxSIRgQQEQIA +BgUCS4Ts4wAKCRCgT/sbfcrp09HnAJ0dELKCp7WoOoAPVBHez/sfHAmgAwCdG64t +bjYwj5CamCOhDvuNjfbUpBSIRgQQEQIABgUCS4W+PgAKCRDCeBwaRrHv4S4EAKCV +LKV3q7PiVV5rb9T+s5uyrETBsgCfUVhchd+Ha5nbduvnF25C0Eswouq5AQ0ES37q +CgEIAK8GnjvPPqWqcNCmLyuscuTKPjqTyaA3xVVYNX+8hMD1iK4VAGf3QfKExVnN +QLvLpnknnKK/caaXFME9t4L0BTjCJRYJiDpoWImwu5fTRIyfIIy4vv5vPErqqKen +7dII6gptC2i538ntj7k8qkhewKJuTOVpE1eLHe3RxuP8rsv1AsvjJ+6WGZlFYINZ ++d0pxSOhdPN9WoTCl9JfkTQrnoVPClzG/euOkF5fUThL90gt31iN+RjB5DeWTPB/ +jDrq6t5spA8hTKvQ+UB65chI6TzrCr+k8f5D9AR0Fkf9KPFOL7+U9o6Ap9yur5sn +njDP4fFVhazVyljUwwPvJ5jjS1cAEQEAAYkBHwQYAQIACQUCS37qCgIbDAAKCRBg +TfvyhUEKvpWAB/0YnkJx6/5rIwDh1u5iFdboUCEsX92n9eOilPWw1NWbq/Gdx7+Z +xoRjrGl8e8SxOZJbfyehgPX8NxOrkBfcAOOXmOvXSO1i3HSo2gaQxVh1urXojzID +raUMcltcNeQagdtDfPhYnS25vJnj+H29Dal2FwLJb9wp8QH1DdhUBoqeRQH34REu +fWu0LjF87JjUELhZe0Op4B8HnQV9oGo7W4IYw/3Ek6c5As+WIWSaz0NmHP2Xw+kI +kpC4BVIwG0l2mChAT8Ds+rDLGYA2dxYK39mFSApem2KiXFhAanDBb5XgilmeDepk +A4NAZlDwxoivB/5PTy67pX+AC1JgvPPafUMu +=6Xeh +-----END PGP PUBLIC KEY BLOCK----- + Type Bits KeyID Created Expires Algorithm Use pub 1024 0xA77F2429 2009-01-01 ---------- RSA Sign & Encrypt f16 Fingerprint16 = 33 3A 62 61 2C F3 21 AA 4E 87 47 F2 2F 2C 40 4D @@ -1865,4 +2082,4 @@ DnF3FZZEzV7oqPwC2jzv/1dD6GFhtgy0cnyoPGUJCyc= =nES8 -----END PGP PUBLIC KEY BLOCK----- -$Revision: 8.29 $, Last updated $Date: 2009/01/06 05:59:03 $ +$Revision: 8.36 $, Last updated $Date: 2011/01/28 21:17:54 $ diff --git a/contrib/sendmail/RELEASE_NOTES b/contrib/sendmail/RELEASE_NOTES index 4e1e8f38305..f96f8cfb069 100644 --- a/contrib/sendmail/RELEASE_NOTES +++ b/contrib/sendmail/RELEASE_NOTES @@ -1,11 +1,75 @@ SENDMAIL RELEASE NOTES - $Id: RELEASE_NOTES,v 8.1963 2009/12/23 04:43:46 ca Exp $ + $Id: RELEASE_NOTES,v 8.1991 2011/05/15 04:28:16 ca Exp $ This listing shows the version of the sendmail binary, the version of the sendmail configuration files, the date of release, and a summary of the changes in that release. +8.14.5/8.14.5 2011/05/17 + Do not cache SMTP extensions across connections as the cache + is based on hostname which may not be a unique identifier + for a server, i.e., different machines may have the + same hostname but provide different SMTP extensions. + Problem noted by Jim Hermann. + Avoid an out-of-bounds access in case a resolver reply for a DNS + map lookup returns a size larger than 1K. Based on a + patch from Dr. Werner Fink of SuSE. + If a job is aborted using the interrupt signal (e.g., control-C from + the keyboard), perform minimal cleanup to avoid invoking + functions that are not signal-safe. Note: in previous + versions the mail might have been queued up already + and would be delivered subsequently, now an interrupt + will always remove the queue files and thus prevent + delivery. + Per RFC 6176, when operating as a TLS client, do not offer SSLv2. + Since TLS session resumption is never used as a client, disable + use of RFC 4507-style session tickets. + Work around gcc4 versions which reverse 25 years of history and + no longer align char buffers on the stack, breaking calls + to resolver functions on strict alignment platforms. + Found by Stuart Henderson of OpenBSD. + Read at most two AUTH lines from a server greeting (up to two + lines are read because servers may use "AUTH mechs" and + "AUTH=mechs"). Otherwise a malicious server may exhaust + the memory of the client. Bug report by Nils of MWR + InfoSecurity. + Avoid triggering an assertion in the OpenLDAP code when the + connection to an LDAP server is lost while making a query. + Problem noted and patch provided by Andy Fiddaman. + If ConnectOnlyTo is set and sendmail is compiled with NETINET6 + it would try to use an IPv6 address if an IPv4 (or + unparseable) address is specified. + If SASLv2 is used, make sure that the macro {auth_authen} is + stored in xtext format to avoid problems with parsing + it. Problem noted by Christophe Wolfhugel. + CONFIG: FEATURE(`ldap_routing') in 8.14.4 tried to add a missing + -T that is required, but failed for some cases + that did not use LDAP. This change has been undone + until a better solution can be implemented. Problem + found by Andy Fiddaman. + CONFIG: Add cf/ostype/solaris11.m4 for Solaris11 support. + Contributed by Casper Dik of Oracle. + CONTRIB: qtool.pl: Deal with H entries that do not have a + letter between the question marks. Patch from + Stefan Christensen. + DOC: Use a better description for the -i option in sendmail. + Patch from Mitchell Berger. + Portability: + Add support for Darwin 10.x (Mac OS X 10.6). + Enable HAVE_NANOSLEEP for FreeBSD 3 and later. Patch + from John Marshall. + Enable HAVE_NANOSLEEP for OpenBSD 4.3 and later. + Use new directory "/system/volatile" for PidFile on + Solaris 11. Patch from Casper Dik of Oracle. + Fix compilation on Solaris 11 (and maybe some other + OSs) when using OpenSSL 1.0. Based on patch from + Jan Pechanec of Oracle. + Set SOCKADDR_LEN_T and SOCKOPT_LEN_T to socklen_t + for Solaris 11. Patch from Roger Faulkner of Oracle. + New Files: + cf/ostype/solaris11.m4 + 8.14.4/8.14.4 2009/12/30 SECURITY: Handle bogus certificates containing NUL characters in CNs by placing a string indicating a bad certificate diff --git a/contrib/sendmail/cf/cf/submit.cf b/contrib/sendmail/cf/cf/submit.cf index 5286c681be0..6cc386a6a69 100644 --- a/contrib/sendmail/cf/cf/submit.cf +++ b/contrib/sendmail/cf/cf/submit.cf @@ -1,5 +1,5 @@ # -# Copyright (c) 1998-2004, 2009 Sendmail, Inc. and its suppliers. +# Copyright (c) 1998-2004, 2009, 2010 Sendmail, Inc. and its suppliers. # All rights reserved. # Copyright (c) 1983, 1995 Eric P. Allman. All rights reserved. # Copyright (c) 1988, 1993 @@ -16,8 +16,8 @@ ##### ##### SENDMAIL CONFIGURATION FILE ##### -##### built by ca@wiz.smi.sendmail.com on Tue Dec 22 20:49:09 PST 2009 -##### in /extra/home/ca/sm-8.14.4/OpenSource/sendmail-8.14.4/cf/cf +##### built by ca@wiz.smi.sendmail.com on Sat May 14 21:31:14 PDT 2011 +##### in /extra/home/ca/sm-8.14.5/OpenSource/sendmail-8.14.5/cf/cf ##### using ../ as configuration include directory ##### ###################################################################### @@ -27,7 +27,7 @@ ###################################################################### ###################################################################### -##### $Id: cfhead.m4,v 8.120 2009/01/23 22:39:21 ca Exp $ ##### +##### $Id: cfhead.m4,v 8.121 2010/01/07 18:20:19 ca Exp $ ##### ##### $Id: cf.m4,v 8.32 1999/02/07 07:26:14 gshapiro Exp $ ##### ##### $Id: submit.mc,v 8.14 2006/04/05 05:54:41 ca Exp $ ##### ##### $Id: msp.m4,v 1.33 2004/02/09 22:32:38 ca Exp $ ##### @@ -35,7 +35,7 @@ ##### $Id: no_default_msa.m4,v 8.2 2001/02/14 05:03:22 gshapiro Exp $ ##### -##### $Id: proto.m4,v 8.741 2009/12/11 00:04:53 ca Exp $ ##### +##### $Id: proto.m4,v 8.744 2010/11/23 20:29:47 guenther Exp $ ##### # level 10 config file format V10/Berkeley @@ -114,7 +114,7 @@ D{MTAHost}[127.0.0.1] # Configuration version number -DZ8.14.4/Submit +DZ8.14.5/Submit ############### @@ -992,7 +992,6 @@ R< $* > $* $: $2 - ###################################################################### ### check_mail -- check SMTP `MAIL FROM:' command argument ###################################################################### diff --git a/contrib/sendmail/cf/feature/ldap_routing.m4 b/contrib/sendmail/cf/feature/ldap_routing.m4 index 227060c20e9..e9b488039cb 100644 --- a/contrib/sendmail/cf/feature/ldap_routing.m4 +++ b/contrib/sendmail/cf/feature/ldap_routing.m4 @@ -1,6 +1,6 @@ divert(-1) # -# Copyright (c) 1999-2002, 2004, 2007, 2009 Sendmail, Inc. and its suppliers. +# Copyright (c) 1999-2002, 2004, 2007 Sendmail, Inc. and its suppliers. # All rights reserved. # # By using this file, you agree to the terms and conditions set @@ -10,7 +10,7 @@ divert(-1) # divert(0) -VERSIONID(`$Id: ldap_routing.m4,v 8.17 2009/06/26 21:11:08 ca Exp $') +VERSIONID(`$Id: ldap_routing.m4,v 8.18 2010/01/05 00:57:27 ca Exp $') divert(-1) # Check first two arguments. If they aren't set, may need to warn in proto.m4 @@ -35,40 +35,12 @@ ifelse(len(X`'_ARG6_), `1', `define(`_LDAP_ROUTE_MAPTEMP_', `_QUEUE_')', _ARG6_, `tempfail', `define(`_LDAP_ROUTE_MAPTEMP_', `_TEMPFAIL_')', _ARG6_, `queue', `define(`_LDAP_ROUTE_MAPTEMP_', `_QUEUE_')') -define(`_ATMPF_', `')dnl -dnl check whether arg contains -T`'_ATMPF_ -dnl unless it is a sequence map or just LDAP -dnl note: this does not work if ARG1 begins with space(s), however, as -dnl we issue a warning, hopefully the user will fix it... -ifelse(defn(`_ARG1_'), `', `', - defn(`_ARG1_'), `LDAP', `', - `ifelse(index(_ARG1_, `sequence '), `0', `', - `ifelse(index(_ARG1_, _ATMPF_), `-1', - `errprint(`*** WARNING: missing -T'_ATMPF_` in first argument of FEATURE(`ldap_routing') -') - define(`_ABP_', index(_ARG1_, ` ')) - define(`_NARG1_', `substr(_ARG1_, 0, _ABP_) -T'_ATMPF_` substr(_ARG1_, _ABP_)') - ') - ') - ') -ifelse(defn(`_ARG2_'), `', `', - defn(`_ARG2_'), `LDAP', `', - `ifelse(index(_ARG2_, `sequence '), `0', `', - `ifelse(index(_ARG2_, _ATMPF_), `-1', - `errprint(`*** WARNING: missing -T'_ATMPF_` in second argument of FEATURE(`ldap_routing') -') - define(`_ABP_', index(_ARG2_, ` ')) - define(`_NARG2_', `substr(_ARG2_, 0, _ABP_) -T'_ATMPF_` substr(_ARG2_, _ABP_)') - ') - ') - ') - LOCAL_CONFIG # LDAP routing maps Kldapmh ifelse(len(X`'_ARG1_), `1', `ldap -1 -T -v mailHost -k (&(objectClass=inetLocalMailRecipient)(mailLocalAddress=%0))', - defn(`_NARG1_'), `', `_ARG1_', `_NARG1_') + `_ARG1_') Kldapmra ifelse(len(X`'_ARG2_), `1', `ldap -1 -T -v mailRoutingAddress -k (&(objectClass=inetLocalMailRecipient)(mailLocalAddress=%0))', - defn(`_NARG2_'), `', `_ARG2_', `_NARG2_') + `_ARG2_') diff --git a/contrib/sendmail/cf/m4/cfhead.m4 b/contrib/sendmail/cf/m4/cfhead.m4 index c2d0df7c8e1..fbb9476b76a 100644 --- a/contrib/sendmail/cf/m4/cfhead.m4 +++ b/contrib/sendmail/cf/m4/cfhead.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 1998-2004, 2009 Sendmail, Inc. and its suppliers. +# Copyright (c) 1998-2004, 2009, 2010 Sendmail, Inc. and its suppliers. # All rights reserved. # Copyright (c) 1983, 1995 Eric P. Allman. All rights reserved. # Copyright (c) 1988, 1993 @@ -189,6 +189,7 @@ SLocal_tls_server') define(`LOCAL_RULE_3', `divert(2)') define(`LOCAL_CONFIG', `divert(6)') define(`MAILER_DEFINITIONS', `divert(7)') +define(`LOCAL_DNSBL', `divert(8)') define(`LOCAL_NET_CONFIG', `define(`_LOCAL_RULES_', 1)divert(1)') define(`UUCPSMTP', `R DOL(*) < @ $1 .UUCP > DOL(*) DOL(1) < @ $2 > DOL(2)') define(`CONCAT', `$1$2$3$4$5$6$7') @@ -308,4 +309,4 @@ define(`confMILTER_MACROS_EOM', `{msg_id}') divert(0)dnl -VERSIONID(`$Id: cfhead.m4,v 8.120 2009/01/23 22:39:21 ca Exp $') +VERSIONID(`$Id: cfhead.m4,v 8.121 2010/01/07 18:20:19 ca Exp $') diff --git a/contrib/sendmail/cf/m4/proto.m4 b/contrib/sendmail/cf/m4/proto.m4 index c021581c377..8bfd9de93ea 100644 --- a/contrib/sendmail/cf/m4/proto.m4 +++ b/contrib/sendmail/cf/m4/proto.m4 @@ -1,6 +1,6 @@ divert(-1) # -# Copyright (c) 1998-2009 Sendmail, Inc. and its suppliers. +# Copyright (c) 1998-2010 Sendmail, Inc. and its suppliers. # All rights reserved. # Copyright (c) 1983, 1995 Eric P. Allman. All rights reserved. # Copyright (c) 1988, 1993 @@ -13,10 +13,10 @@ divert(-1) # divert(0) -VERSIONID(`$Id: proto.m4,v 8.741 2009/12/11 00:04:53 ca Exp $') +VERSIONID(`$Id: proto.m4,v 8.744 2010/11/23 20:29:47 guenther Exp $') # level CF_LEVEL config file format -V`'CF_LEVEL/ifdef(`VENDOR_NAME', `VENDOR_NAME', `Berkeley') +V`'CF_LEVEL`'ifdef(`NO_VENDOR',`', `/ifdef(`VENDOR_NAME', `VENDOR_NAME', `Berkeley')') divert(-1) dnl if MAILER(`local') not defined: do it ourself; be nice @@ -1795,7 +1795,7 @@ ifdef(`_CONN_CONTROL_',`dnl ifdef(`_CONN_CONTROL_IMMEDIATE_',`',`dnl dnl workspace: ignored... R$* $: $>"ConnControl" dummy')', `dnl') -undivert(8) +undivert(8)dnl LOCAL_DNSBL ifdef(`_REQUIRE_RDNS_', `dnl R$* $: $&{client_addr} $| $&{client_resolve} R$=R $* $@ RELAY We relay for these diff --git a/contrib/sendmail/cf/m4/version.m4 b/contrib/sendmail/cf/m4/version.m4 index 5ad5ffb9024..566c3a514af 100644 --- a/contrib/sendmail/cf/m4/version.m4 +++ b/contrib/sendmail/cf/m4/version.m4 @@ -1,6 +1,6 @@ divert(-1) # -# Copyright (c) 1998-2009 Sendmail, Inc. and its suppliers. +# Copyright (c) 1998-2011 Sendmail, Inc. and its suppliers. # All rights reserved. # Copyright (c) 1983 Eric P. Allman. All rights reserved. # Copyright (c) 1988, 1993 @@ -11,8 +11,8 @@ divert(-1) # the sendmail distribution. # # -VERSIONID(`$Id: version.m4,v 8.205 2009/12/23 04:43:09 ca Exp $') +VERSIONID(`$Id: version.m4,v 8.214 2011/04/26 23:02:36 ca Exp $') # divert(0) # Configuration version number -DZ8.14.4`'ifdef(`confCF_VERSION', `/confCF_VERSION') +DZ8.14.5`'ifdef(`confCF_VERSION', `/confCF_VERSION') diff --git a/contrib/sendmail/cf/ostype/solaris11.m4 b/contrib/sendmail/cf/ostype/solaris11.m4 new file mode 100644 index 00000000000..a48b0779c78 --- /dev/null +++ b/contrib/sendmail/cf/ostype/solaris11.m4 @@ -0,0 +1,22 @@ +divert(-1) +# +# Copyright (c) 2011 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# This ostype file is suitable for use on Solaris 11 and later systems, +# make use of /system/volatile, introduced in Solaris 11. +# + +divert(0) +VERSIONID(`$Id: solaris11.m4,v 1.1 2011/01/24 21:22:08 ca Exp $') +divert(-1) + +ifdef(`UUCP_MAILER_ARGS',, `define(`UUCP_MAILER_ARGS', `uux - -r -a$g $h!rmail ($u)')') +define(`confEBINDIR', `/usr/lib')dnl +define(`confPID_FILE', `/system/volatile/sendmail.pid')dnl +define(`_NETINET6_')dnl +FEATURE(`local_lmtp')dnl diff --git a/contrib/sendmail/contrib/qtool.pl b/contrib/sendmail/contrib/qtool.pl index f2d33c27b4a..c2a67f83d56 100755 --- a/contrib/sendmail/contrib/qtool.pl +++ b/contrib/sendmail/contrib/qtool.pl @@ -3,7 +3,7 @@ ## Copyright (c) 1998-2002 Sendmail, Inc. and its suppliers. ## All rights reserved. ## -## $Id: qtool.pl,v 8.30 2009/03/04 16:57:30 ca Exp $ +## $Id: qtool.pl,v 8.31 2010/11/10 19:11:54 ca Exp $ ## use strict; use File::Basename; @@ -607,7 +607,7 @@ sub parse_header $first_char = substr($line, 0, 1); if ($first_char eq "?") { - $line = substr($line, 3); + $line = (split(/\?/, $line,3))[2]; } elsif ($first_char eq "\t") { diff --git a/contrib/sendmail/doc/op/op.me b/contrib/sendmail/doc/op/op.me index be078102436..1e7d3702388 100644 --- a/contrib/sendmail/doc/op/op.me +++ b/contrib/sendmail/doc/op/op.me @@ -9,7 +9,7 @@ .\" the sendmail distribution. .\" .\" -.\" $Id: op.me,v 8.745 2009/12/13 04:12:46 ca Exp $ +.\" $Id: op.me,v 8.747 2010/05/08 04:18:27 ca Exp $ .\" .\" eqn op.me | pic | troff -me .\" @@ -90,7 +90,7 @@ Sendmail, Inc. .de Ve Version \\$2 .. -.Ve $Revision: 8.745 $ +.Ve $Revision: 8.747 $ .rm Ve .sp For Sendmail Version 8.14 @@ -1095,6 +1095,9 @@ The number of envelope recipients for this message (after aliasing and forwarding). .ip msgid The message id of the message (from the header). +.ip bodytype +The message body type (7BIT or 8BITMIME), +as determined from the envelope. .ip proto The protocol used to receive this message (e.g., ESMTP or UUCP) .ip daemon @@ -5154,7 +5157,8 @@ FAIL cert presented but could not be verified, e.g., the signing CA is missing. NONE STARTTLS has not been performed. TEMP temporary error occurred. -PROTOCOL some protocol error occurred. +PROTOCOL some protocol error occurred + at the ESMTP level (not TLS). SOFTWARE STARTTLS handshake failed, which is a fatal error for this session, the e-mail will be queued. @@ -11463,7 +11467,7 @@ replace it with a blank sheet for double-sided output. .\".sz 10 .\"Eric Allman .\".sp -.\"Version $Revision: 8.745 $ +.\"Version $Revision: 8.747 $ .\".ce 0 .bp 3 .ce diff --git a/contrib/sendmail/include/sm/conf.h b/contrib/sendmail/include/sm/conf.h index 5b1875426af..b47a5f8cbec 100644 --- a/contrib/sendmail/include/sm/conf.h +++ b/contrib/sendmail/include/sm/conf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2009 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2011 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -10,7 +10,7 @@ * the sendmail distribution. * * - * $Id: conf.h,v 1.139 2009/06/16 23:41:32 ca Exp $ + * $Id: conf.h,v 1.144 2011/05/03 16:24:00 ca Exp $ */ /* @@ -381,6 +381,12 @@ typedef int pid_t; # ifndef __svr4__ # define __svr4__ /* use all System V Release 4 defines below */ # endif /* ! __svr4__ */ +# if SOLARIS >= 21100 +# include +# endif /* SOLARIS >= 21100 */ +# ifndef _PATH_VARRUN +# define _PATH_VARRUN "/var/run/" +# endif /* _PATH_VARRUN */ # define GIDSET_T gid_t # define USE_SA_SIGACTION 1 /* use sa_sigaction field */ # define BROKEN_PTHREAD_SLEEP 1 /* sleep after pthread_create() fails */ @@ -443,7 +449,7 @@ typedef int pid_t; # endif /* SOLARIS >= 20700 || (SOLARIS < 10000 && SOLARIS >= 207) */ # if SOLARIS >= 20800 || (SOLARIS < 10000 && SOLARIS >= 208) # undef _PATH_SENDMAILPID /* tmpfs /var/run added in 2.8 */ -# define _PATH_SENDMAILPID "/var/run/sendmail.pid" +# define _PATH_SENDMAILPID _PATH_VARRUN "sendmail.pid" # ifndef SMRSH_CMDDIR # define SMRSH_CMDDIR "/var/adm/sm.bin" # endif /* ! SMRSH_CMDDIR */ @@ -461,6 +467,8 @@ typedef int pid_t; # if SOLARIS >= 21100 || (SOLARIS < 10000 && SOLARIS >= 211) # define GETLDAPALIASBYNAME_VERSION 2 /* changed in S11 */ # define HAVE_NANOSLEEP 1 /* moved from librt to libc in S11 */ +# define SOCKADDR_LEN_T socklen_t /* arg#3 to accept, getsockname */ +# define SOCKOPT_LEN_T socklen_t /* arg#5 to getsockopt */ # endif /* SOLARIS >= 21100 || (SOLARIS < 10000 && SOLARIS >= 211) */ # ifndef HASGETUSERSHELL # define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps pre-2.7 */ @@ -1014,6 +1022,9 @@ extern unsigned int sleepX __P((unsigned int seconds)); # if __FreeBSD_version >= 222000 /* 2.2.2-release and later */ # define HASSETUSERCONTEXT 1 /* BSDI-style login classes */ # endif /* __FreeBSD_version >= 222000 */ +# if __FreeBSD_version >= 300000 /* 3.0.0-release and later */ +# define HAVE_NANOSLEEP 1 /* has nanosleep(2) */ +# endif /* __FreeBSD_version >= 300000 */ # if __FreeBSD_version >= 330000 /* 3.3.0-release and later */ # ifndef SMRSH_CMDDIR # define SMRSH_CMDDIR "/usr/libexec/sm.bin" @@ -1055,6 +1066,9 @@ extern unsigned int sleepX __P((unsigned int seconds)); # if OpenBSD >= 200505 # undef NETISO /* iso.h removed in 3.7 */ # endif /* OpenBSD >= 200505 */ +# if OpenBSD >= 200800 +# define HAVE_NANOSLEEP 1 /* has nanosleep(2) */ +# endif /* OpenBSD >= 200800 */ # endif /* defined(__OpenBSD__) */ # endif /* defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) */ @@ -2808,7 +2822,7 @@ struct utsname # if _FFR_LINUX_MHNL && defined(__linux__) && MAXHOSTNAMELEN < 255 /* - ** override Linux wierdness: a FQHN can be 255 chars long + ** override Linux weirdness: a FQHN can be 255 chars long ** SUSv3 requires HOST_NAME_MAX ("Maximum length of a host ** name (not including the terminating null) as returned from the ** gethostname() function.") to be at least 255. c.f.: diff --git a/contrib/sendmail/libmilter/docs/overview.html b/contrib/sendmail/libmilter/docs/overview.html index 5c6f21ce4ce..d6e3bbaf6b9 100644 --- a/contrib/sendmail/libmilter/docs/overview.html +++ b/contrib/sendmail/libmilter/docs/overview.html @@ -4,7 +4,7 @@

Technical Overview

@@ -126,7 +126,7 @@ messages may be sent in a single connection. Note also that a message or connection may be aborted by either the remote host or the MTA at any point during the SMTP transaction. -f this occurs during a message (between the MAIL command and the final "."), +If this occurs during a message (between the MAIL command and the final "."), the filter's xxfi_abort routine will be called. xxfi_close is called any time the diff --git a/contrib/sendmail/libmilter/docs/smfi_stop.html b/contrib/sendmail/libmilter/docs/smfi_stop.html index 87ecdb27175..5d25882d737 100644 --- a/contrib/sendmail/libmilter/docs/smfi_stop.html +++ b/contrib/sendmail/libmilter/docs/smfi_stop.html @@ -2,7 +2,7 @@ smfi_stop

smfi_stop

@@ -42,7 +42,7 @@ which may then exit or warm-restart. -
ArgumentDescription
voidTakes no arguement. + Takes no argument.
diff --git a/contrib/sendmail/libmilter/docs/xxfi_envrcpt.html b/contrib/sendmail/libmilter/docs/xxfi_envrcpt.html index 9fb4ce873a8..67a8cf54f37 100644 --- a/contrib/sendmail/libmilter/docs/xxfi_envrcpt.html +++ b/contrib/sendmail/libmilter/docs/xxfi_envrcpt.html @@ -2,7 +2,7 @@ xxfi_envrcpt

xxfi_envrcpt

@@ -71,7 +71,8 @@ Handle the envelope RCPT command. SMFIS_ACCEPT - Accept recipient. xxfi_abort will not be called. + Accept this message. + xxfi_abort will not be called. @@ -87,7 +88,7 @@ Handle the envelope RCPT command.
-Copyright (c) 2000, 2003 Sendmail, Inc. and its suppliers. +Copyright (c) 2000, 2003, 2010 Sendmail, Inc. and its suppliers. All rights reserved.
By using this file, you agree to the terms and conditions set diff --git a/contrib/sendmail/libmilter/engine.c b/contrib/sendmail/libmilter/engine.c index a2d3e1e3f3f..92c8e6d1822 100644 --- a/contrib/sendmail/libmilter/engine.c +++ b/contrib/sendmail/libmilter/engine.c @@ -9,7 +9,7 @@ */ #include -SM_RCSID("@(#)$Id: engine.c,v 8.166 2009/11/06 00:57:07 ca Exp $") +SM_RCSID("@(#)$Id: engine.c,v 8.167 2011/03/03 06:09:15 ca Exp $") #include "libmilter.h" @@ -284,7 +284,7 @@ mi_engine(ctx) if (mi_stop() == MILTER_ABRT) { if (ctx->ctx_dbg > 3) - sm_dprintf("[%ld] milter_abort\n", + sm_dprintf("[%lu] milter_abort\n", (long) ctx->ctx_id); ret = MI_FAILURE; break; @@ -315,7 +315,7 @@ mi_engine(ctx) cmd < SMFIC_VALIDCMD) { if (ctx->ctx_dbg > 5) - sm_dprintf("[%ld] mi_engine: mi_rd_cmd error (%x)\n", + sm_dprintf("[%lu] mi_engine: mi_rd_cmd error (%x)\n", (long) ctx->ctx_id, (int) cmd); /* @@ -328,7 +328,7 @@ mi_engine(ctx) break; } if (ctx->ctx_dbg > 4) - sm_dprintf("[%ld] got cmd '%c' len %d\n", + sm_dprintf("[%lu] got cmd '%c' len %d\n", (long) ctx->ctx_id, cmd, (int) len); for (i = 0; i < ncmds; i++) { @@ -339,7 +339,7 @@ mi_engine(ctx) { /* unknown command */ if (ctx->ctx_dbg > 1) - sm_dprintf("[%ld] cmd '%c' unknown\n", + sm_dprintf("[%lu] cmd '%c' unknown\n", (long) ctx->ctx_id, cmd); ret = MI_FAILURE; break; @@ -348,7 +348,7 @@ mi_engine(ctx) { /* stop for now */ if (ctx->ctx_dbg > 1) - sm_dprintf("[%ld] cmd '%c' not impl\n", + sm_dprintf("[%lu] cmd '%c' not impl\n", (long) ctx->ctx_id, cmd); ret = MI_FAILURE; break; @@ -357,14 +357,14 @@ mi_engine(ctx) /* is new state ok? */ newstate = cmds[i].cm_next; if (ctx->ctx_dbg > 5) - sm_dprintf("[%ld] cur %x new %x nextmask %x\n", + sm_dprintf("[%lu] cur %x new %x nextmask %x\n", (long) ctx->ctx_id, curstate, newstate, next_states[curstate]); if (newstate != ST_NONE && !trans_ok(curstate, newstate)) { if (ctx->ctx_dbg > 1) - sm_dprintf("[%ld] abort: cur %d (%x) new %d (%x) next %x\n", + sm_dprintf("[%lu] abort: cur %d (%x) new %d (%x) next %x\n", (long) ctx->ctx_id, curstate, MI_MASK(curstate), newstate, MI_MASK(newstate), @@ -434,7 +434,7 @@ mi_engine(ctx) else if (r == _SMFIS_ABORT) { if (ctx->ctx_dbg > 5) - sm_dprintf("[%ld] function returned abort\n", + sm_dprintf("[%lu] function returned abort\n", (long) ctx->ctx_id); ret = MI_FAILURE; break; @@ -1122,7 +1122,7 @@ st_optionneg(g) fix_stm(ctx); if (ctx->ctx_dbg > 3) - sm_dprintf("[%ld] milter_negotiate:" + sm_dprintf("[%lu] milter_negotiate:" " mta_actions=0x%lx, mta_flags=0x%lx" " actions=0x%lx, flags=0x%lx\n" , (long) ctx->ctx_id @@ -1131,7 +1131,7 @@ st_optionneg(g) #if _FFR_MILTER_CHECK if (ctx->ctx_dbg > 3) - sm_dprintf("[%ld] milter_negotiate:" + sm_dprintf("[%lu] milter_negotiate:" " testmode=%d, pflags2mta=%X, internal_pflags=%X\n" , (long) ctx->ctx_id, testmode , ctx->ctx_pflags2mta, internal_pflags); diff --git a/contrib/sendmail/libmilter/sm_gethost.c b/contrib/sendmail/libmilter/sm_gethost.c index 5706b892b8d..8f2b339cf7c 100644 --- a/contrib/sendmail/libmilter/sm_gethost.c +++ b/contrib/sendmail/libmilter/sm_gethost.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2001, 2004 Sendmail, Inc. and its suppliers. + * Copyright (c) 1999-2001, 2004, 2010 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set @@ -9,7 +9,7 @@ */ #include -SM_RCSID("@(#)$Id: sm_gethost.c,v 8.27 2004/08/20 21:12:37 ca Exp $") +SM_RCSID("@(#)$Id: sm_gethost.c,v 8.29 2010/07/27 01:09:31 ca Exp $") #include #if NETINET || NETINET6 @@ -30,7 +30,7 @@ SM_RCSID("@(#)$Id: sm_gethost.c,v 8.27 2004/08/20 21:12:37 ca Exp $") #if NETINET6 && NEEDSGETIPNODE -static struct hostent *getipnodebyname __P((char *, int, int, int *)); +static struct hostent *sm_getipnodebyname __P((const char *, int, int, int *)); # ifndef AI_ADDRCONFIG # define AI_ADDRCONFIG 0 /* dummy */ @@ -43,8 +43,8 @@ static struct hostent *getipnodebyname __P((char *, int, int, int *)); # endif /* ! AI_DEFAULT */ static struct hostent * -getipnodebyname(name, family, flags, err) - char *name; +sm_getipnodebyname(name, family, flags, err) + const char *name; int family; int flags; int *err; @@ -77,6 +77,8 @@ freehostent(h) return; } +#else /* NEEDSGETIPNODE && NETINET6 */ +#define sm_getipnodebyname getipnodebyname #endif /* NEEDSGETIPNODE && NETINET6 */ struct hostent * @@ -107,7 +109,7 @@ mi_gethostbyname(name, family) # if ADDRCONFIG_IS_BROKEN flags &= ~AI_ADDRCONFIG; # endif /* ADDRCONFIG_IS_BROKEN */ - h = getipnodebyname(name, family, flags, &err); + h = sm_getipnodebyname(name, family, flags, &err); SM_SET_H_ERRNO(err); # else /* NETINET6 */ h = gethostbyname(name); diff --git a/contrib/sendmail/libmilter/worker.c b/contrib/sendmail/libmilter/worker.c index 28d404fa3a2..aa1bd576829 100644 --- a/contrib/sendmail/libmilter/worker.c +++ b/contrib/sendmail/libmilter/worker.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004, 2007, 2009 Sendmail, Inc. and its suppliers. + * Copyright (c) 2003-2004, 2007, 2009-2011 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set @@ -11,7 +11,7 @@ */ #include -SM_RCSID("@(#)$Id: worker.c,v 8.17 2009/06/15 15:34:54 ca Exp $") +SM_RCSID("@(#)$Id: worker.c,v 8.19 2011/02/14 23:33:48 ca Exp $") #include "libmilter.h" @@ -165,7 +165,9 @@ mi_start_session(ctx) { static long id = 0; - SM_ASSERT(Tskmgr.tm_signature == TM_SIGNATURE); + /* this can happen if the milter is shutting down */ + if (Tskmgr.tm_signature != TM_SIGNATURE) + return MI_FAILURE; SM_ASSERT(ctx != NULL); POOL_LEV_DPRINTF(4, ("PIPE r=[%d] w=[%d]", RD_PIPE, WR_PIPE)); TASKMGR_LOCK(); @@ -215,6 +217,41 @@ mi_close_session(ctx) return MI_SUCCESS; } +/* +** NONBLOCKING -- set nonblocking mode for a file descriptor. +** +** Parameters: +** fd -- file descriptor +** name -- name for (error) logging +** +** Returns: +** MI_SUCCESS/MI_FAILURE +*/ + +static int +nonblocking(int fd, const char *name) +{ + int r; + + errno = 0; + r = fcntl(fd, F_GETFL, 0); + if (r == -1) + { + smi_log(SMI_LOG_ERR, "fcntl(%s, F_GETFL)=%s", + name, sm_errstring(errno)); + return MI_FAILURE; + } + errno = 0; + r = fcntl(fd, F_SETFL, r | O_NONBLOCK); + if (r == -1) + { + smi_log(SMI_LOG_ERR, "fcntl(%s, F_SETFL, O_NONBLOCK)=%s", + name, sm_errstring(errno)); + return MI_FAILURE; + } + return MI_SUCCESS; +} + /* ** MI_POOL_CONTROLER_INIT -- Launch the worker pool controller ** Must be called before starting sessions. @@ -246,6 +283,12 @@ mi_pool_controller_init() sm_errstring(errno)); return MI_FAILURE; } + r = nonblocking(WR_PIPE, "WR_PIPE"); + if (r != MI_SUCCESS) + return r; + r = nonblocking(RD_PIPE, "RD_PIPE"); + if (r != MI_SUCCESS) + return r; (void) smutex_init(&Tskmgr.tm_w_mutex); (void) scond_init(&Tskmgr.tm_w_cond); @@ -495,25 +538,23 @@ mi_pool_controller(arg) /* has a worker signaled an end of task ? */ if (WAIT_FD(i) == RD_PIPE) { - char evt = 0; - int r = 0; + char evts[256]; + ssize_t r; POOL_LEV_DPRINTF(4, ("PIPE WILL READ evt = %08X %08X", pfd[i].events, pfd[i].revents)); - if ((pfd[i].revents & MI_POLL_RD_FLAGS) != 0) + r = 1; + while ((pfd[i].revents & MI_POLL_RD_FLAGS) != 0 + && r != -1) { - r = read(RD_PIPE, &evt, sizeof(evt)); - if (r == sizeof(evt)) - { - /* Do nothing */ - } + r = read(RD_PIPE, evts, sizeof(evts)); } POOL_LEV_DPRINTF(4, ("PIPE DONE READ i=[%d] fd=[%d] r=[%d] evt=[%d]", - i, RD_PIPE, r, evt)); + i, RD_PIPE, (int) r, evts[0])); if ((pfd[i].revents & ~MI_POLL_RD_FLAGS) != 0) { diff --git a/contrib/sendmail/libsm/ldap.c b/contrib/sendmail/libsm/ldap.c index 7ee57fcbb68..9ae233f3ce1 100644 --- a/contrib/sendmail/libsm/ldap.c +++ b/contrib/sendmail/libsm/ldap.c @@ -11,7 +11,7 @@ #define LDAP_DEPRECATED 1 #include -SM_RCSID("@(#)$Id: ldap.c,v 1.83 2009/06/19 22:02:26 guenther Exp $") +SM_RCSID("@(#)$Id: ldap.c,v 1.85 2011/04/18 22:20:20 ca Exp $") #if LDAPMAP # include @@ -1098,10 +1098,8 @@ sm_ldap_results(lmap, msgid, flags, delim, rpool, result, if (ret == 0) save_errno = ETIMEDOUT; - else + else if (ret == LDAP_RES_SEARCH_RESULT) { - int rc; - /* ** We may have gotten an LDAP_RES_SEARCH_RESULT response ** with an error inside it, so we have to extract that @@ -1109,11 +1107,21 @@ sm_ldap_results(lmap, msgid, flags, delim, rpool, result, ** to an LDAP proxy whose backend has gone down. */ - save_errno = ldap_parse_result(lmap->ldap_ld, lmap->ldap_res, - &rc, NULL, NULL, NULL, NULL, 0); - if (save_errno == LDAP_SUCCESS) - save_errno = rc; + if (lmap->ldap_res == NULL) + save_errno = LDAP_UNAVAILABLE; + else + { + int rc; + + save_errno = ldap_parse_result(lmap->ldap_ld, + lmap->ldap_res, &rc, NULL, NULL, + NULL, NULL, 0); + if (save_errno == LDAP_SUCCESS) + save_errno = rc; + } } + else + save_errno = sm_ldap_geterrno(lmap->ldap_ld); if (save_errno != LDAP_SUCCESS) { statp = EX_TEMPFAIL; diff --git a/contrib/sendmail/makemap/makemap.c b/contrib/sendmail/makemap/makemap.c index cacec001e76..f06ed076008 100644 --- a/contrib/sendmail/makemap/makemap.c +++ b/contrib/sendmail/makemap/makemap.c @@ -20,7 +20,7 @@ SM_IDSTR(copyright, Copyright (c) 1992, 1993\n\ The Regents of the University of California. All rights reserved.\n") -SM_IDSTR(id, "@(#)$Id: makemap.c,v 8.179 2008/04/14 02:06:16 ca Exp $") +SM_IDSTR(id, "@(#)$Id: makemap.c,v 8.180 2010/11/23 02:35:08 gshapiro Exp $") #include @@ -238,7 +238,7 @@ main(argc, argv) if ((cfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, cfile, SM_IO_RDONLY, NULL)) == NULL) { - sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "makemap: %s: %s", + sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "makemap: %s: %s\n", cfile, sm_errstring(errno)); exit(EX_NOINPUT); } diff --git a/contrib/sendmail/src/Makefile.m4 b/contrib/sendmail/src/Makefile.m4 index 0fa337467d4..7bcd24d9eeb 100644 --- a/contrib/sendmail/src/Makefile.m4 +++ b/contrib/sendmail/src/Makefile.m4 @@ -1,4 +1,4 @@ -dnl $Id: Makefile.m4,v 8.121 2009/12/15 22:39:23 ca Exp $ +dnl $Id: Makefile.m4,v 8.126 2010/11/24 19:59:54 gshapiro Exp $ include(confBUILDTOOLSDIR`/M4/switch.m4') define(`confREQUIRE_LIBSM', `true') diff --git a/contrib/sendmail/src/conf.c b/contrib/sendmail/src/conf.c index 8d8f9ed6b14..ffc6f205c70 100644 --- a/contrib/sendmail/src/conf.c +++ b/contrib/sendmail/src/conf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2009 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2010 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -13,7 +13,7 @@ #include -SM_RCSID("@(#)$Id: conf.c,v 8.1153 2009/12/18 17:25:12 ca Exp $") +SM_RCSID("@(#)$Id: conf.c,v 8.1168 2011/01/25 18:31:30 ca Exp $") #include #include @@ -50,8 +50,11 @@ static int get_num_procs_online __P((void)); static int add_hostnames __P((SOCKADDR *)); #if NETINET6 && NEEDSGETIPNODE -static struct hostent *getipnodebyname __P((char *, int, int, int *)); -static struct hostent *getipnodebyaddr __P((char *, int, int, int *)); +static struct hostent *sm_getipnodebyname __P((const char *, int, int, int *)); +static struct hostent *sm_getipnodebyaddr __P((const void *, size_t, int, int *)); +#else /* NETINET6 && NEEDSGETIPNODE */ +#define sm_getipnodebyname getipnodebyname +#define sm_getipnodebyaddr getipnodebyaddr #endif /* NETINET6 && NEEDSGETIPNODE */ @@ -2600,7 +2603,7 @@ setproctitle(fmt, va_alist) ** none. */ -/*VARARGS2*/ +/*VARARGS3*/ void #ifdef __STDC__ sm_setproctitle(bool status, ENVELOPE *e, const char *fmt, ...) @@ -4188,7 +4191,7 @@ strstr(big, little) /* ** SM_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX ** -** Some operating systems have wierd problems with the gethostbyXXX +** Some operating systems have weird problems with the gethostbyXXX ** routines. For example, Solaris versions at least through 2.3 ** don't properly deliver a canonical h_name field. This tries to ** work around these problems. @@ -4212,8 +4215,8 @@ strstr(big, little) # endif /* ! AI_ALL */ static struct hostent * -getipnodebyname(name, family, flags, err) - char *name; +sm_getipnodebyname(name, family, flags, err) + const char *name; int family; int flags; int *err; @@ -4236,9 +4239,9 @@ getipnodebyname(name, family, flags, err) } static struct hostent * -getipnodebyaddr(addr, len, family, err) - char *addr; - int len; +sm_getipnodebyaddr(addr, len, family, err) + const void *addr; + size_t len; int family; int *err; { @@ -4305,7 +4308,7 @@ sm_gethostbyname(name, family) # if ADDRCONFIG_IS_BROKEN flags &= ~AI_ADDRCONFIG; # endif /* ADDRCONFIG_IS_BROKEN */ - h = getipnodebyname(name, family, flags, &err); + h = sm_getipnodebyname(name, family, flags, &err); SM_SET_H_ERRNO(err); # else /* NETINET6 */ h = gethostbyname(name); @@ -4344,7 +4347,7 @@ sm_gethostbyname(name, family) hbuf, family); # if NETINET6 - h = getipnodebyname(hbuf, family, flags, &err); + h = sm_getipnodebyname(hbuf, family, flags, &err); SM_SET_H_ERRNO(err); save_errno = errno; # else /* NETINET6 */ @@ -4441,7 +4444,7 @@ sm_gethostbyaddr(addr, len, type) { int err; - hp = getipnodebyaddr(addr, len, type, &err); + hp = sm_getipnodebyaddr(addr, len, type, &err); SM_SET_H_ERRNO(err); } # else /* NETINET6 */ @@ -4864,6 +4867,7 @@ load_if_names() switch (af) { case AF_INET6: + SETV6LOOPBACKADDRFOUND(*sa); # ifdef __KAME__ /* convert into proper scoped address */ if ((IN6_IS_ADDR_LINKLOCAL(&sa->sin6.sin6_addr) || @@ -5063,6 +5067,7 @@ load_if_names() # if NETINET6 case AF_INET6: + SETV6LOOPBACKADDRFOUND(*sa); # ifdef __KAME__ /* convert into proper scoped address */ if ((IN6_IS_ADDR_LINKLOCAL(&sa->sin6.sin6_addr) || @@ -5928,6 +5933,9 @@ char *OsCompileOptions[] = #if HASWAITPID "HASWAITPID", #endif /* HASWAITPID */ +#if HAVE_NANOSLEEP + "HAVE_NANOSLEEP", +#endif /* HAVE_NANOSLEEP */ #if IDENTPROTO "IDENTPROTO", #endif /* IDENTPROTO */ @@ -6018,6 +6026,9 @@ char *OsCompileOptions[] = #ifdef USESYSCTL "USESYSCTL", #endif /* USESYSCTL */ +#if USE_OPENSSL_ENGINE + "USE_OPENSSL_ENGINE", +#endif /* USE_OPENSSL_ENGINE */ #if USING_NETSCAPE_LDAP "USING_NETSCAPE_LDAP", #endif /* USING_NETSCAPE_LDAP */ @@ -6321,7 +6332,7 @@ char *FFRCompileOptions[] = #endif /* _FFR_QUEUE_SCHED_DBG */ #if _FFR_RCPTTHROTDELAY /* configurable delay for BadRcptThrottle */ - "_FFR_RCPTTHROTDELAY" + "_FFR_RCPTTHROTDELAY", #endif /* _FFR_RCPTTHROTDELAY */ #if _FFR_REDIRECTEMPTY /* diff --git a/contrib/sendmail/src/daemon.c b/contrib/sendmail/src/daemon.c index 983ad2fe3ed..a1dcbe85043 100644 --- a/contrib/sendmail/src/daemon.c +++ b/contrib/sendmail/src/daemon.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2007, 2009 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2007, 2009, 2010 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -14,7 +14,7 @@ #include #include "map.h" -SM_RCSID("@(#)$Id: daemon.c,v 8.683 2009/12/18 01:12:40 ca Exp $") +SM_RCSID("@(#)$Id: daemon.c,v 8.691 2011/01/25 18:31:30 ca Exp $") #if defined(SOCK_STREAM) || defined(__GNU_LIBRARY__) # define USE_SOCK_STREAM 1 @@ -1267,7 +1267,8 @@ setupdaemon(daemonaddr) case AF_INET6: if (IN6_IS_ADDR_UNSPECIFIED(&daemonaddr->sin6.sin6_addr)) daemonaddr->sin6.sin6_addr = - LocalDaemon ? in6addr_loopback : in6addr_any; + (LocalDaemon && V6LoopbackAddrFound) ? + in6addr_loopback : in6addr_any; port = daemonaddr->sin6.sin6_port; break; #endif /* NETINET6 */ @@ -2219,7 +2220,8 @@ makeconnection(host, port, mci, e, enough) #if NETINET6 case AF_INET6: if (IN6_IS_ADDR_UNSPECIFIED(&clt_addr.sin6.sin6_addr)) - clt_addr.sin6.sin6_addr = LocalDaemon ? + clt_addr.sin6.sin6_addr = + (LocalDaemon && V6LoopbackAddrFound) ? in6addr_loopback : in6addr_any; else clt_bind = true; @@ -2665,6 +2667,7 @@ gothostent: #if NETINET case AF_INET: addr.sin.sin_addr.s_addr = ConnectOnlyTo.sin.sin_addr.s_addr; + addr.sa.sa_family = ConnectOnlyTo.sa.sa_family; break; #endif /* NETINET */ @@ -2872,7 +2875,10 @@ nextaddr: /* Use the configured HeloName as appropriate */ if (HeloName != NULL && HeloName[0] != '\0') + { + SM_FREE_CLR(mci->mci_heloname); mci->mci_heloname = newstr(HeloName); + } mci_setstat(mci, EX_OK, NULL, NULL); return EX_OK; diff --git a/contrib/sendmail/src/deliver.c b/contrib/sendmail/src/deliver.c index 0322c956ef2..acd977f5a4b 100644 --- a/contrib/sendmail/src/deliver.c +++ b/contrib/sendmail/src/deliver.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2008 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2010 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -14,7 +14,7 @@ #include #include -SM_RCSID("@(#)$Id: deliver.c,v 8.1020 2009/12/18 17:08:01 ca Exp $") +SM_RCSID("@(#)$Id: deliver.c,v 8.1024 2011/01/12 23:52:59 ca Exp $") #if HASSETUSERCONTEXT # include @@ -1850,7 +1850,7 @@ deliver(e, firstto) ** If we are running SMTP, we just need to clean up. */ - /* XXX this seems a bit wierd */ + /* XXX this seems a bit weird */ if (ctladdr == NULL && m != ProgMailer && m != FileMailer && bitset(QGOODUID, e->e_from.q_flags)) ctladdr = &e->e_from; @@ -2144,6 +2144,7 @@ tryhost: mci->mci_lastuse = curtime(); mci->mci_deliveries = 0; mci->mci_exitstat = i; + mci_clr_extensions(mci); # if NAMED_BIND mci->mci_herrno = h_errno; # endif /* NAMED_BIND */ @@ -3104,7 +3105,7 @@ reconnect: /* after switching to an encrypted connection */ mci->mci_state != MCIS_CLOSED) { SET_HELO(mci->mci_flags); - mci->mci_flags &= ~MCIF_EXTENS; + mci_clr_extensions(mci); goto reconnect; } } @@ -3157,7 +3158,7 @@ reconnect: /* after switching to an encrypted connection */ &mci->mci_out, mci->mci_conn, tmo) == 0) { - mci->mci_flags &= ~MCIF_EXTENS; + mci_clr_extensions(mci); mci->mci_flags |= MCIF_AUTHACT| MCIF_ONLY_EHLO; goto reconnect; @@ -6111,12 +6112,13 @@ starttls(m, mci, e) return EX_TEMPFAIL; # if USE_OPENSSL_ENGINE - if (!SSL_set_engine(NULL)) + if (!SSLEngineInitialized && !SSL_set_engine(NULL)) { sm_syslog(LOG_ERR, NOQID, "STARTTLS=client, SSL_set_engine=failed"); return EX_TEMPFAIL; } + SSLEngineInitialized = true; # endif /* USE_OPENSSL_ENGINE */ smtpmessage("STARTTLS", m, mci); diff --git a/contrib/sendmail/src/domain.c b/contrib/sendmail/src/domain.c index 394b0d3f9fb..21442b37973 100644 --- a/contrib/sendmail/src/domain.c +++ b/contrib/sendmail/src/domain.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2004, 2006 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2004, 2006, 2010 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1986, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -15,9 +15,9 @@ #include "map.h" #if NAMED_BIND -SM_RCSID("@(#)$Id: domain.c,v 8.202 2006/12/19 01:15:07 ca Exp $ (with name server)") +SM_RCSID("@(#)$Id: domain.c,v 8.204 2010/06/29 15:35:33 ca Exp $ (with name server)") #else /* NAMED_BIND */ -SM_RCSID("@(#)$Id: domain.c,v 8.202 2006/12/19 01:15:07 ca Exp $ (without name server)") +SM_RCSID("@(#)$Id: domain.c,v 8.204 2010/06/29 15:35:33 ca Exp $ (without name server)") #endif /* NAMED_BIND */ #if NAMED_BIND @@ -25,25 +25,6 @@ SM_RCSID("@(#)$Id: domain.c,v 8.202 2006/12/19 01:15:07 ca Exp $ (without name s # include -/* -** The standard udp packet size PACKETSZ (512) is not sufficient for some -** nameserver answers containing very many resource records. The resolver -** may switch to tcp and retry if it detects udp packet overflow. -** Also note that the resolver routines res_query and res_search return -** the size of the *un*truncated answer in case the supplied answer buffer -** it not big enough to accommodate the entire answer. -*/ - -# ifndef MAXPACKET -# define MAXPACKET 8192 /* max packet size used internally by BIND */ -# endif /* ! MAXPACKET */ - -typedef union -{ - HEADER qb1; - unsigned char qb2[MAXPACKET]; -} querybuf; - # ifndef MXHOSTBUFSIZE # define MXHOSTBUFSIZE (128 * MAXMXHOSTS) # endif /* ! MXHOSTBUFSIZE */ diff --git a/contrib/sendmail/src/envelope.c b/contrib/sendmail/src/envelope.c index 022c3ca8b2d..18defd2ef9a 100644 --- a/contrib/sendmail/src/envelope.c +++ b/contrib/sendmail/src/envelope.c @@ -13,7 +13,7 @@ #include -SM_RCSID("@(#)$Id: envelope.c,v 8.310 2009/12/18 17:08:01 ca Exp $") +SM_RCSID("@(#)$Id: envelope.c,v 8.312 2010/02/03 16:36:40 ca Exp $") /* ** CLRSESSENVELOPE -- clear session oriented data in an envelope @@ -246,12 +246,14 @@ dropenvelope(e, fulldrop, split) e->e_flags |= EF_FATALERRS|EF_CLRQUEUE; } + e->e_flags &= ~EF_QUEUERUN; for (q = e->e_sendqueue; q != NULL; q = q->q_next) { if (QS_IS_UNDELIVERED(q->q_state)) queueit = true; + /* see if a notification is needed */ if (bitset(QPINGONFAILURE, q->q_flags) && ((IS_MSG_ERR(msg_timeout) && diff --git a/contrib/sendmail/src/err.c b/contrib/sendmail/src/err.c index 5825666e623..baa355a5960 100644 --- a/contrib/sendmail/src/err.c +++ b/contrib/sendmail/src/err.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2003, 2010 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -13,7 +13,7 @@ #include -SM_RCSID("@(#)$Id: err.c,v 8.196 2006/11/10 23:14:08 ca Exp $") +SM_RCSID("@(#)$Id: err.c,v 8.205 2010/02/03 23:22:41 ca Exp $") #if LDAPMAP # include @@ -359,7 +359,7 @@ usrerr(fmt, va_alist) ** increments Errors. */ -/*VARARGS1*/ +/*VARARGS2*/ void #ifdef __STDC__ usrerrenh(char *enhsc, const char *fmt, ...) @@ -427,6 +427,7 @@ usrerrenh(enhsc, fmt, va_alist) if (QuickAbort) sm_exc_raisenew_x(&EtypeQuickAbort, 1); } + /* ** MESSAGE -- print message (not necessarily an error) ** @@ -473,11 +474,12 @@ message(msg, va_alist) case '5': if (CurEnv->e_rpool == NULL && CurEnv->e_message != NULL) sm_free(CurEnv->e_message); - CurEnv->e_message = - sm_rpool_strdup_x(CurEnv->e_rpool, errtxt); + CurEnv->e_message = sm_rpool_strdup_x(CurEnv->e_rpool, errtxt); break; } } + + /* ** NMESSAGE -- print message (not necessarily an error) ** diff --git a/contrib/sendmail/src/main.c b/contrib/sendmail/src/main.c index 1bbb070dace..4d2318fb435 100644 --- a/contrib/sendmail/src/main.c +++ b/contrib/sendmail/src/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2006, 2008, 2009 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2006, 2008, 2009, 2011 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -26,7 +26,7 @@ SM_UNUSED(static char copyright[]) = The Regents of the University of California. All rights reserved.\n"; #endif /* ! lint */ -SM_RCSID("@(#)$Id: main.c,v 8.971 2009/12/18 17:08:01 ca Exp $") +SM_RCSID("@(#)$Id: main.c,v 8.976 2011/03/15 23:14:36 ca Exp $") #if NETINET || NETINET6 @@ -304,6 +304,9 @@ main(argc, argv, envp) SubmitMode = SUBMIT_UNKNOWN; #if _FFR_LOCAL_DAEMON LocalDaemon = false; +# if NETINET6 + V6LoopbackAddrFound = false; +# endif /* NETINET6 */ #endif /* _FFR_LOCAL_DAEMON */ #if XDEBUG checkfd012("after openlog"); @@ -1308,7 +1311,7 @@ main(argc, argv, envp) (void) getfallbackmxrr(FallbackMX); #endif /* NAMED_BIND */ - if (SuperSafe == SAFE_INTERACTIVE && CurEnv->e_sendmode != SM_DELIVER) + if (SuperSafe == SAFE_INTERACTIVE && !SM_IS_INTERACTIVE(CurEnv->e_sendmode)) { (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "WARNING: SuperSafe=interactive should only be used with\n DeliveryMode=interactive\n"); @@ -3190,7 +3193,7 @@ sigpipe(sig) ** may resend a message. ** ** Parameters: -** none. +** sig -- incoming signal. ** ** Returns: ** none. @@ -3201,8 +3204,6 @@ sigpipe(sig) ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE ** DOING. -** -** XXX: More work is needed for this signal handler. */ /* ARGSUSED */ @@ -3217,38 +3218,34 @@ intsig(sig) errno = save_errno; CHECK_CRITICAL(sig); sm_allsignals(true); + IntSig = true; - if (sig != 0 && LogLevel > 79) - sm_syslog(LOG_DEBUG, CurEnv->e_id, "interrupt"); FileName = NULL; /* Clean-up on aborted stdin message submission */ - if (CurEnv->e_id != NULL && - (OpMode == MD_SMTP || + if (OpMode == MD_SMTP || OpMode == MD_DELIVER || - OpMode == MD_ARPAFTP)) + OpMode == MD_ARPAFTP) { - register ADDRESS *q; + if (CurEnv->e_id != NULL) + { + char *fn; - /* don't return an error indication */ - CurEnv->e_to = NULL; - CurEnv->e_flags &= ~EF_FATALERRS; - CurEnv->e_flags |= EF_CLRQUEUE; - - /* - ** Spin through the addresses and - ** mark them dead to prevent bounces - */ - - for (q = CurEnv->e_sendqueue; q != NULL; q = q->q_next) - q->q_state = QS_DONTSEND; - - drop = true; + fn = queuename(CurEnv, DATAFL_LETTER); + if (fn != NULL) + (void) unlink(fn); + fn = queuename(CurEnv, ANYQFL_LETTER); + if (fn != NULL) + (void) unlink(fn); + } + _exit(EX_OK); + /* NOTREACHED */ } - else if (OpMode != MD_TEST) - { + + if (sig != 0 && LogLevel > 79) + sm_syslog(LOG_DEBUG, CurEnv->e_id, "interrupt"); + if (OpMode != MD_TEST) unlockqueue(CurEnv); - } finis(drop, false, EX_OK); /* NOTREACHED */ diff --git a/contrib/sendmail/src/map.c b/contrib/sendmail/src/map.c index be88685babd..2eb69588eb8 100644 --- a/contrib/sendmail/src/map.c +++ b/contrib/sendmail/src/map.c @@ -13,7 +13,7 @@ #include -SM_RCSID("@(#)$Id: map.c,v 8.705 2009/08/11 22:22:40 ca Exp $") +SM_RCSID("@(#)$Id: map.c,v 8.706 2010/07/27 03:35:42 ca Exp $") #if LDAPMAP # include @@ -5985,7 +5985,7 @@ stab_map_store(map, lhs, rhs) /* ** STAB_MAP_OPEN -- initialize (reads data file) ** -** This is a wierd case -- it is only intended as a fallback for +** This is a weird case -- it is only intended as a fallback for ** aliases. For this reason, opens for write (only during a ** "newaliases") always fails, and opens for read open the ** actual underlying text file instead of the database. diff --git a/contrib/sendmail/src/mci.c b/contrib/sendmail/src/mci.c index 277011770be..7b171677496 100644 --- a/contrib/sendmail/src/mci.c +++ b/contrib/sendmail/src/mci.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2005 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2005, 2010 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -13,7 +13,7 @@ #include -SM_RCSID("@(#)$Id: mci.c,v 8.221 2007/11/13 23:44:25 gshapiro Exp $") +SM_RCSID("@(#)$Id: mci.c,v 8.223 2010/03/10 04:35:28 ca Exp $") #if NETINET || NETINET6 # include @@ -288,6 +288,32 @@ mci_flush(doquit, allbut) mci_uncache(&MciCache[i], doquit); } } + +/* +** MCI_CLR_EXTENSIONS -- clear knowledge about SMTP extensions +** +** Parameters: +** mci -- the connection to clear. +** +** Returns: +** none. +*/ + +void +mci_clr_extensions(mci) + MCI *mci; +{ + if (mci == NULL) + return; + + mci->mci_flags &= ~MCIF_EXTENS; + mci->mci_maxsize = 0; + mci->mci_min_by = 0; +#if SASL + mci->mci_saslcap = NULL; +#endif /* SASL */ +} + /* ** MCI_GET -- get information about a particular host ** @@ -567,6 +593,7 @@ static struct mcifbits MciFlags[] = { MCIF_CVT7TO8, "CVT7TO8" }, { MCIF_INMIME, "INMIME" }, { MCIF_AUTH, "AUTH" }, + { MCIF_AUTH2, "AUTH2" }, { MCIF_AUTHACT, "AUTHACT" }, { MCIF_ENHSTAT, "ENHSTAT" }, { MCIF_PIPELINED, "PIPELINED" }, diff --git a/contrib/sendmail/src/parseaddr.c b/contrib/sendmail/src/parseaddr.c index 19bcf739bd9..9135c22c41f 100644 --- a/contrib/sendmail/src/parseaddr.c +++ b/contrib/sendmail/src/parseaddr.c @@ -13,7 +13,7 @@ #include -SM_RCSID("@(#)$Id: parseaddr.c,v 8.403 2008/02/08 02:27:35 ca Exp $") +SM_RCSID("@(#)$Id: parseaddr.c,v 8.404 2010/07/27 03:35:42 ca Exp $") #include #include "map.h" @@ -319,7 +319,7 @@ delim: ** is invalid and should be "repaired". ** ** Returns: -** true -- if the address has any "wierd" characters or +** true -- if the address has any "weird" characters or ** non-printable characters or if a quote is unbalanced. ** false -- otherwise. */ diff --git a/contrib/sendmail/src/queue.c b/contrib/sendmail/src/queue.c index 194f5250d66..16142d9c33e 100644 --- a/contrib/sendmail/src/queue.c +++ b/contrib/sendmail/src/queue.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2009 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2009, 2011 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -14,7 +14,7 @@ #include #include -SM_RCSID("@(#)$Id: queue.c,v 8.987 2009/12/18 17:08:01 ca Exp $") +SM_RCSID("@(#)$Id: queue.c,v 8.991 2011/03/15 23:14:36 ca Exp $") #include @@ -203,7 +203,7 @@ static const char *FSPath[MAXFILESYS]; /* pathnames for file systems */ ** tag -- should be a unique id to avoid misinterpretations by others. ** idea: hash over configuration data that will be stored here. ** NumFileSys -- number of file systems. -** FileSys -- (arrary of) structure for used file systems. +** FileSys -- (array of) structure for used file systems. ** RSATmpCnt -- counter for number of uses of ephemeral RSA key. ** QShm -- (array of) structure for information about queue directories. */ @@ -633,7 +633,6 @@ queueup(e, announce, msync) } /* output inode number of data file */ - /* XXX should probably include device major/minor too */ if (e->e_dfino != -1) { (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "I%ld/%ld/%llu\n", @@ -5195,7 +5194,11 @@ queuename(e, type) /* Assign an ID if needed */ if (e->e_id == NULL) + { + if (IntSig) + return NULL; assign_queueid(e); + } type = queue_letter(e, type); /* begin of filename */ @@ -5239,7 +5242,11 @@ queuename(e, type) else { if (e->e_qgrp == NOQGRP || e->e_qdir == NOQDIR) + { + if (IntSig) + return NULL; (void) setnewqueue(e); + } if (type == DATAFL_LETTER) { qd = e->e_dfqdir; @@ -5279,6 +5286,8 @@ queuename(e, type) break; default: + if (IntSig) + return NULL; sm_abort("queuename: bad queue file type %d", type); } diff --git a/contrib/sendmail/src/readcf.c b/contrib/sendmail/src/readcf.c index c6d48a8cfea..7bc70c2ca1d 100644 --- a/contrib/sendmail/src/readcf.c +++ b/contrib/sendmail/src/readcf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2006, 2008, 2009 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2006, 2008-2010 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -14,12 +14,13 @@ #include #include -SM_RCSID("@(#)$Id: readcf.c,v 8.674 2009/10/26 17:47:00 ca Exp $") +SM_RCSID("@(#)$Id: readcf.c,v 8.684 2011/03/15 17:29:29 guenther Exp $") #if NETINET || NETINET6 # include #endif /* NETINET || NETINET6 */ + #define SECONDS #define MINUTES * 60 #define HOUR * 3600 @@ -114,7 +115,15 @@ readcf(cfname, safe, e) LineNumber = 0; #if STARTTLS - Srv_SSL_Options = Clt_SSL_Options = SSL_OP_ALL; + Srv_SSL_Options = SSL_OP_ALL; + Clt_SSL_Options = SSL_OP_ALL +#ifdef SSL_OP_NO_SSLv2 + | SSL_OP_NO_SSLv2 +#endif +#ifdef SSL_OP_NO_TICKET + | SSL_OP_NO_TICKET +#endif + ; #endif /* STARTTLS */ if (DontLockReadFiles) sff |= SFF_NOLOCK; @@ -2271,6 +2280,10 @@ static struct optioninfo # define O_RCPTTHROTDELAY 0xe6 { "BadRcptThrottleDelay", O_RCPTTHROTDELAY, OI_SAFE }, #endif /* _FFR_RCPTTHROTDELAY */ +#if 0 && _FFR_QOS && defined(SOL_IP) && defined(IP_TOS) +# define O_INETQOS 0xe7 /* reserved for FFR_QOS */ + { "InetQoS", O_INETQOS, OI_NONE }, +#endif { NULL, '\0', OI_NONE } }; @@ -2285,68 +2298,85 @@ static struct ssl_options /* these are turned on by default */ #ifdef SSL_OP_MICROSOFT_SESS_ID_BUG { "SSL_OP_MICROSOFT_SESS_ID_BUG", SSL_OP_MICROSOFT_SESS_ID_BUG }, -#endif /* SSL_OP_MICROSOFT_SESS_ID_BUG */ +#endif #ifdef SSL_OP_NETSCAPE_CHALLENGE_BUG { "SSL_OP_NETSCAPE_CHALLENGE_BUG", SSL_OP_NETSCAPE_CHALLENGE_BUG }, -#endif /* SSL_OP_NETSCAPE_CHALLENGE_BUG */ +#endif #ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG { "SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG }, -#endif /* SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG */ +#endif #ifdef SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG { "SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG }, -#endif /* SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG */ +#endif #ifdef SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER { "SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER }, -#endif /* SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER */ +#endif #ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING { "SSL_OP_MSIE_SSLV2_RSA_PADDING", SSL_OP_MSIE_SSLV2_RSA_PADDING }, -#endif /* SSL_OP_MSIE_SSLV2_RSA_PADDING */ +#endif #ifdef SSL_OP_SSLEAY_080_CLIENT_DH_BUG { "SSL_OP_SSLEAY_080_CLIENT_DH_BUG", SSL_OP_SSLEAY_080_CLIENT_DH_BUG }, -#endif /* SSL_OP_SSLEAY_080_CLIENT_DH_BUG */ +#endif #ifdef SSL_OP_TLS_D5_BUG { "SSL_OP_TLS_D5_BUG", SSL_OP_TLS_D5_BUG }, -#endif /* SSL_OP_TLS_D5_BUG */ +#endif #ifdef SSL_OP_TLS_BLOCK_PADDING_BUG { "SSL_OP_TLS_BLOCK_PADDING_BUG", SSL_OP_TLS_BLOCK_PADDING_BUG }, -#endif /* SSL_OP_TLS_BLOCK_PADDING_BUG */ +#endif #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS { "SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS", SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS }, -#endif /* SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS */ +#endif +#ifdef SSL_OP_ALL { "SSL_OP_ALL", SSL_OP_ALL }, +#endif +#ifdef SSL_OP_NO_QUERY_MTU + { "SSL_OP_NO_QUERY_MTU", SSL_OP_NO_QUERY_MTU }, +#endif +#ifdef SSL_OP_COOKIE_EXCHANGE + { "SSL_OP_COOKIE_EXCHANGE", SSL_OP_COOKIE_EXCHANGE }, +#endif +#ifdef SSL_OP_NO_TICKET + { "SSL_OP_NO_TICKET", SSL_OP_NO_TICKET }, +#endif #ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION { "SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION", SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION }, -#endif /* SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION */ +#endif +#ifdef SSL_OP_SINGLE_ECDH_USE + { "SSL_OP_SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE }, +#endif +#ifdef SSL_OP_SINGLE_DH_USE + { "SSL_OP_SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE }, +#endif #ifdef SSL_OP_EPHEMERAL_RSA { "SSL_OP_EPHEMERAL_RSA", SSL_OP_EPHEMERAL_RSA }, -#endif /* SSL_OP_EPHEMERAL_RSA */ +#endif #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE { "SSL_OP_CIPHER_SERVER_PREFERENCE", SSL_OP_CIPHER_SERVER_PREFERENCE }, -#endif /* SSL_OP_CIPHER_SERVER_PREFERENCE */ +#endif #ifdef SSL_OP_TLS_ROLLBACK_BUG { "SSL_OP_TLS_ROLLBACK_BUG", SSL_OP_TLS_ROLLBACK_BUG }, -#endif /* SSL_OP_TLS_ROLLBACK_BUG */ +#endif #ifdef SSL_OP_NO_SSLv2 { "SSL_OP_NO_SSLv2", SSL_OP_NO_SSLv2 }, -#endif /* SSL_OP_NO_SSLv2 */ +#endif #ifdef SSL_OP_NO_SSLv3 { "SSL_OP_NO_SSLv3", SSL_OP_NO_SSLv3 }, -#endif /* SSL_OP_NO_SSLv3 */ +#endif #ifdef SSL_OP_NO_TLSv1 { "SSL_OP_NO_TLSv1", SSL_OP_NO_TLSv1 }, -#endif /* SSL_OP_NO_TLSv1 */ +#endif #ifdef SSL_OP_PKCS1_CHECK_1 { "SSL_OP_PKCS1_CHECK_1", SSL_OP_PKCS1_CHECK_1 }, -#endif /* SSL_OP_PKCS1_CHECK_1 */ +#endif #ifdef SSL_OP_PKCS1_CHECK_2 { "SSL_OP_PKCS1_CHECK_2", SSL_OP_PKCS1_CHECK_2 }, -#endif /* SSL_OP_PKCS1_CHECK_2 */ +#endif #ifdef SSL_OP_NETSCAPE_CA_DN_BUG { "SSL_OP_NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG }, -#endif /* SSL_OP_NETSCAPE_CA_DN_BUG */ +#endif #ifdef SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG { "SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG }, -#endif /* SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG */ +#endif { NULL, 0 } }; #endif /* STARTTLS && _FFR_TLS_1 */ @@ -2639,6 +2669,7 @@ setoption(opt, val, safe, sticky, e) set_delivery_mode(*val, e); break; + default: syserr("Unknown delivery mode %c", *val); finis(false, true, EX_USAGE); @@ -3446,7 +3477,7 @@ setoption(opt, val, safe, sticky, e) ConnectOnlyTo.sa.sa_family = AF_UNSPEC; # if NETINET6 if (anynet_pton(AF_INET6, val, - &ConnectOnlyTo.sin6.sin6_addr) != 1) + &ConnectOnlyTo.sin6.sin6_addr) == 1) ConnectOnlyTo.sa.sa_family = AF_INET6; else # endif /* NETINET6 */ diff --git a/contrib/sendmail/src/sendmail.8 b/contrib/sendmail/src/sendmail.8 index e5ce9aeef9d..5097f22326b 100644 --- a/contrib/sendmail/src/sendmail.8 +++ b/contrib/sendmail/src/sendmail.8 @@ -9,9 +9,9 @@ .\" the sendmail distribution. .\" .\" -.\" $Id: sendmail.8,v 8.59 2009/04/10 17:49:19 gshapiro Exp $ +.\" $Id: sendmail.8,v 8.60 2011/03/07 23:44:48 ca Exp $ .\" -.TH SENDMAIL 8 "$Date: 2009/04/10 17:49:19 $" +.TH SENDMAIL 8 "$Date: 2011/03/07 23:44:48 $" .SH NAME sendmail \- an electronic mail transport agent @@ -224,7 +224,9 @@ If not specified, ``Received:'' lines in the message are counted. .TP .B \-i -Ignore dots alone on lines by themselves in incoming messages. +Do not strip a leading dot from lines in incoming messages, +and do not treat a dot on a line by itself +as the end of an incoming message. This should be set if you are reading data from a file. .TP .BI "\-L " tag diff --git a/contrib/sendmail/src/sendmail.h b/contrib/sendmail/src/sendmail.h index b170c2bbb3d..39ba16cf0cc 100644 --- a/contrib/sendmail/src/sendmail.h +++ b/contrib/sendmail/src/sendmail.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2009 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2011 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -52,7 +52,7 @@ #ifdef _DEFINE # ifndef lint -SM_UNUSED(static char SmailId[]) = "@(#)$Id: sendmail.h,v 8.1068 2009/12/18 17:08:01 ca Exp $"; +SM_UNUSED(static char SmailId[]) = "@(#)$Id: sendmail.h,v 8.1089 2011/03/15 23:14:36 ca Exp $"; # endif /* ! lint */ #endif /* _DEFINE */ @@ -327,7 +327,7 @@ typedef struct address ADDRESS; (s) == QS_SENT || \ (s) == QS_DISCARDED) #define QS_IS_DEAD(s) ((s) >= QS_DONTSEND) - +#define QS_IS_TEMPFAIL(s) ((s) == QS_QUEUEUP || (s) == QS_RETRY) #define NULLADDR ((ADDRESS *) NULL) @@ -721,17 +721,20 @@ MCI #if STARTTLS #define MCIF_TLS 0x00100000 /* STARTTLS supported */ #define MCIF_TLSACT 0x00200000 /* STARTTLS active */ -#define MCIF_EXTENS (MCIF_EXPN | MCIF_SIZE | MCIF_8BITMIME | MCIF_DSN | MCIF_8BITOK | MCIF_AUTH | MCIF_ENHSTAT | MCIF_TLS) #else /* STARTTLS */ -#define MCIF_EXTENS (MCIF_EXPN | MCIF_SIZE | MCIF_8BITMIME | MCIF_DSN | MCIF_8BITOK | MCIF_AUTH | MCIF_ENHSTAT) +#define MCIF_TLS 0 +#define MCIF_TLSACT 0 #endif /* STARTTLS */ #define MCIF_DLVR_BY 0x00400000 /* DELIVERBY */ #if _FFR_IGNORE_EXT_ON_HELO # define MCIF_HELO 0x00800000 /* we used HELO: ignore extensions */ #endif /* _FFR_IGNORE_EXT_ON_HELO */ #define MCIF_INLONGLINE 0x01000000 /* in the middle of a long line */ +#define MCIF_AUTH2 0x02000000 /* got 2 AUTH lines */ #define MCIF_ONLY_EHLO 0x10000000 /* use only EHLO in smtpinit */ +#define MCIF_EXTENS (MCIF_EXPN | MCIF_SIZE | MCIF_8BITMIME | MCIF_DSN | MCIF_8BITOK | MCIF_AUTH | MCIF_ENHSTAT | MCIF_TLS | MCIF_AUTH2) + /* states */ #define MCIS_CLOSED 0 /* no traffic on this connection */ #define MCIS_OPENING 1 /* sending initial protocol */ @@ -749,6 +752,7 @@ extern void mci_close __P((MCI *, char *where)); extern void mci_dump __P((SM_FILE_T *, MCI *, bool)); extern void mci_dump_all __P((SM_FILE_T *, bool)); extern void mci_flush __P((bool, MCI *)); +extern void mci_clr_extensions __P((MCI *)); extern MCI *mci_get __P((char *, MAILER *)); extern int mci_lock_host __P((MCI *)); extern bool mci_match __P((char *, MAILER *)); @@ -1167,6 +1171,33 @@ struct hostsig_t typedef struct hostsig_t HOSTSIG_T; +/* +** The standard udp packet size PACKETSZ (512) is not sufficient for some +** nameserver answers containing very many resource records. The resolver +** may switch to tcp and retry if it detects udp packet overflow. +** Also note that the resolver routines res_query and res_search return +** the size of the *un*truncated answer in case the supplied answer buffer +** it not big enough to accommodate the entire answer. +*/ + +# ifndef MAXPACKET +# define MAXPACKET 8192 /* max packet size used internally by BIND */ +# endif /* ! MAXPACKET */ + +/* +** The resolver functions res_{send,query,querydomain} expect the +** answer buffer to be aligned, but some versions of gcc4 reverse +** 25 years of history and no longer align char buffers on the +** stack, resulting in crashes on strict-alignment platforms. Use +** this union when putting the buffer on the stack to force the +** alignment, then cast to (HEADER *) or (unsigned char *) as needed. +*/ +typedef union +{ + HEADER qb1; + unsigned char qb2[MAXPACKET]; +} querybuf; + /* functions */ extern bool getcanonname __P((char *, int, bool, int *)); extern int getmxrr __P((char *, char **, unsigned short *, bool, int *, bool, int *)); @@ -1246,11 +1277,15 @@ MAP #define MF_OPENBOGUS 0x00800000 /* open failed, don't call map_close */ #define MF_CLOSING 0x01000000 /* map is being closed */ -#define DYNOPENMAP(map) if (!bitset(MF_OPEN, (map)->map_mflags)) \ - { \ - if (!openmap(map)) \ - return NULL; \ - } +#define DYNOPENMAP(map) \ + do \ + { \ + if (!bitset(MF_OPEN, (map)->map_mflags)) \ + { \ + if (!openmap(map)) \ + return NULL; \ + } \ + } while (0) /* indices for map_actions */ @@ -1569,8 +1604,19 @@ extern void stabapply __P((void (*)(STAB *, int), int)); #if _FFR_LOCAL_DAEMON EXTERN bool LocalDaemon; +# if NETINET6 +EXTERN bool V6LoopbackAddrFound; /* found an IPv6 loopback address */ +# define SETV6LOOPBACKADDRFOUND(sa) \ + do \ + { \ + if (isloopback(sa)) \ + V6LoopbackAddrFound = true; \ + } while (0) +# endif /* NETINET6 */ #else /* _FFR_LOCAL_DAEMON */ # define LocalDaemon false +# define V6LoopbackAddrFound false +# define SETV6LOOPBACKADDRFOUND(sa) #endif /* _FFR_LOCAL_DAEMON */ /* Note: see also include/sendmail/pathnames.h: GET_CLIENT_CF */ @@ -1585,6 +1631,7 @@ EXTERN bool LocalDaemon; #define SM_DEFER 'd' /* defer map lookups as well as queue */ #define SM_VERIFY 'v' /* verify only (used internally) */ #define DM_NOTSET (-1) /* DeliveryMode (per daemon) option not set */ +# define SM_IS_INTERACTIVE(m) ((m) == SM_DELIVER) #define WILL_BE_QUEUED(m) ((m) == SM_QUEUE || (m) == SM_DEFER) @@ -2100,7 +2147,11 @@ extern void inittimeouts __P((char *, bool)); */ /* macros for debugging flags */ -#define tTd(flag, level) (tTdvect[flag] >= (unsigned char)level) +#if NOT_SENDMAIL +# define tTd(flag, level) (tTdvect[flag] >= (unsigned char)level) +#else +# define tTd(flag, level) (tTdvect[flag] >= (unsigned char)level && !IntSig) +#endif #define tTdlevel(flag) (tTdvect[flag]) /* variables */ @@ -2123,22 +2174,26 @@ extern unsigned char tTdvect[100]; /* trace vector */ */ /* set exit status */ -#define setstat(s) { \ - if (ExitStat == EX_OK || ExitStat == EX_TEMPFAIL) \ - ExitStat = s; \ - } +#define setstat(s) \ + do \ + { \ + if (ExitStat == EX_OK || ExitStat == EX_TEMPFAIL) \ + ExitStat = s; \ + } while (0) #define STRUCTCOPY(s, d) d = s /* free a pointer if it isn't NULL and set it to NULL */ #define SM_FREE_CLR(p) \ - if ((p) != NULL) \ - { \ - sm_free(p); \ - (p) = NULL; \ - } \ - else + do \ + { \ + if ((p) != NULL) \ + { \ + sm_free(p); \ + (p) = NULL; \ + } \ + } while (0) /* ** Update a permanent string variable with a new value. @@ -2185,6 +2240,15 @@ extern unsigned char tTdvect[100]; /* trace vector */ #define XS_DEFAULT 0 #define XS_STARTTLS 1 #define XS_AUTH 2 +#define XS_GREET 3 +#define XS_EHLO 4 +#define XS_MAIL 5 +#define XS_RCPT 6 +#define XS_DATA 7 +#define XS_EOM 8 +#define XS_DATA2 9 +#define XS_RCPT2 10 +#define XS_QUIT 15 /* ** Global variables. @@ -2363,6 +2427,7 @@ EXTERN char *RunAsUserName; /* user to become for bulk of run */ EXTERN char *SafeFileEnv; /* chroot location for file delivery */ EXTERN char *ServiceSwitchFile; /* backup service switch */ EXTERN char *volatile ShutdownRequest;/* a sendmail shutdown has been requested */ +EXTERN bool volatile IntSig; EXTERN char *SmtpGreeting; /* SMTP greeting message (old $e macro) */ EXTERN char *SmtpPhase; /* current phase in SMTP processing */ EXTERN char SmtpError[MAXLINE]; /* save failure error messages */ @@ -2390,6 +2455,9 @@ extern const SM_EXC_TYPE_T EtypeQuickAbort; /* type of a QuickAbort exception */ EXTERN int ConnectionRateWindowSize; +#if STARTTLS && USE_OPENSSL_ENGINE +EXTERN bool SSLEngineInitialized; +#endif /* STARTTLS && USE_OPENSSL_ENGINE */ /* ** Declarations of useful functions @@ -2442,6 +2510,8 @@ extern int smtprcpt __P((ADDRESS *, MAILER *, MCI *, ENVELOPE *, ADDRESS *, time extern void smtprset __P((MAILER *, MCI *, ENVELOPE *)); #define REPLYTYPE(r) ((r) / 100) /* first digit of reply code */ +#define REPLYCLASS(r) (((r) / 10) % 10) /* second digit of reply code */ +#define REPLYMINOR(r) ((r) % 10) /* last digit of reply code */ #define ISSMTPCODE(c) (isascii(c[0]) && isdigit(c[0]) && \ isascii(c[1]) && isdigit(c[1]) && \ isascii(c[2]) && isdigit(c[2])) diff --git a/contrib/sendmail/src/sm_resolve.c b/contrib/sendmail/src/sm_resolve.c index 6d9c28d73fa..b8a1405f995 100644 --- a/contrib/sendmail/src/sm_resolve.c +++ b/contrib/sendmail/src/sm_resolve.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Sendmail, Inc. and its suppliers. + * Copyright (c) 2000-2004, 2010 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set @@ -44,9 +44,13 @@ #include #if DNSMAP # if NAMED_BIND +# if NETINET +# include +# include +# endif /* NETINET */ # include "sm_resolve.h" -SM_RCSID("$Id: sm_resolve.c,v 8.36 2008/02/11 23:04:16 ca Exp $") +SM_RCSID("$Id: sm_resolve.c,v 8.39 2010/06/29 15:35:33 ca Exp $") static struct stot { @@ -394,7 +398,13 @@ dns_lookup_int(domain, rr_class, rr_type, retrans, retry) time_t save_retrans = 0; int save_retry = 0; DNS_REPLY_T *r = NULL; - unsigned char reply[1024]; + querybuf reply_buf; + unsigned char *reply; + +#define SMRBSIZE sizeof(reply_buf) +#ifndef IP_MAXPACKET +# define IP_MAXPACKET 65535 +#endif if (tTd(8, 16)) { @@ -415,15 +425,44 @@ dns_lookup_int(domain, rr_class, rr_type, retrans, retry) } errno = 0; SM_SET_H_ERRNO(0); - len = res_search(domain, rr_class, rr_type, reply, sizeof(reply)); + reply = (unsigned char *)&reply_buf; + len = res_search(domain, rr_class, rr_type, reply, SMRBSIZE); + if (len >= SMRBSIZE) + { + if (len >= IP_MAXPACKET) + { + if (tTd(8, 4)) + sm_dprintf("dns_lookup: domain=%s, length=%d, default_size=%d, max=%d, status=response too long\n", + domain, len, (int) SMRBSIZE, + IP_MAXPACKET); + } + else + { + if (tTd(8, 6)) + sm_dprintf("dns_lookup: domain=%s, length=%d, default_size=%d, max=%d, status=response longer than default size, resizing\n", + domain, len, (int) SMRBSIZE, + IP_MAXPACKET); + reply = (unsigned char *)sm_malloc(IP_MAXPACKET); + if (reply == NULL) + SM_SET_H_ERRNO(TRY_AGAIN); + else + len = res_search(domain, rr_class, rr_type, + reply, IP_MAXPACKET); + } + } if (tTd(8, 16)) { _res.options = old_options; sm_dprintf("dns_lookup(%s, %d, %s) --> %d\n", domain, rr_class, dns_type_to_string(rr_type), len); } - if (len >= 0) + if (len >= 0 && len < IP_MAXPACKET && reply != NULL) r = parse_dns_reply(reply, len); + if (reply != (unsigned char *)&reply_buf && reply != NULL) + { + sm_free(reply); + reply = NULL; + } if (retrans > 0) _res.retrans = save_retrans; if (retry > 0) diff --git a/contrib/sendmail/src/srvrsmtp.c b/contrib/sendmail/src/srvrsmtp.c index 49016e4572b..1e6a5d2fe29 100644 --- a/contrib/sendmail/src/srvrsmtp.c +++ b/contrib/sendmail/src/srvrsmtp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2008 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2010 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -17,7 +17,7 @@ # include #endif /* MILTER */ -SM_RCSID("@(#)$Id: srvrsmtp.c,v 8.989 2009/12/18 17:08:01 ca Exp $") +SM_RCSID("@(#)$Id: srvrsmtp.c,v 8.1008 2011/01/12 23:52:59 ca Exp $") #include #include @@ -875,10 +875,8 @@ smtp(nullserver, d_flags, e) /* XXX should these be options settable via .cf ? */ /* ssp.min_ssf = 0; is default due to memset() */ - { - ssp.max_ssf = MaxSLBits; - ssp.maxbufsize = MAXOUTLEN; - } + ssp.max_ssf = MaxSLBits; + ssp.maxbufsize = MAXOUTLEN; ssp.security_flags = SASLOpts & SASL_SEC_MASK; sasl_ok = sasl_setprop(conn, SASL_SEC_PROPS, &ssp) == SASL_OK; @@ -909,15 +907,6 @@ smtp(nullserver, d_flags, e) #endif /* SASL */ #if STARTTLS -# if USE_OPENSSL_ENGINE - if (tls_ok_srv && bitset(SRV_OFFER_TLS, features) && - !SSL_set_engine(NULL)) - { - sm_syslog(LOG_ERR, NOQID, - "STARTTLS=server, SSL_set_engine=failed"); - tls_ok_srv = false; - } -# endif /* USE_OPENSSL_ENGINE */ set_tls_rd_tmo(TimeOuts.to_nextcommand); @@ -1836,6 +1825,21 @@ smtp(nullserver, d_flags, e) break; } starttls: +# if USE_OPENSSL_ENGINE + if (!SSLEngineInitialized) + { + if (!SSL_set_engine(NULL)) + { + sm_syslog(LOG_ERR, NOQID, + "STARTTLS=server, SSL_set_engine=failed"); + tls_ok_srv = false; + message("454 4.3.3 TLS not available right now"); + break; + } + else + SSLEngineInitialized = true; + } +# endif /* USE_OPENSSL_ENGINE */ # if TLS_NO_RSA /* ** XXX do we need a temp key ? @@ -2260,8 +2264,7 @@ smtp(nullserver, d_flags, e) message("250-AUTH %s", mechlist); #endif /* SASL */ #if STARTTLS - if (tls_ok_srv && - bitset(SRV_OFFER_TLS, features)) + if (tls_ok_srv && bitset(SRV_OFFER_TLS, features)) message("250-STARTTLS"); #endif /* STARTTLS */ if (DeliverByMin > 0) @@ -2622,7 +2625,7 @@ smtp(nullserver, d_flags, e) goto rcpt_done; } - if (e->e_sendmode != SM_DELIVER + if (!SM_IS_INTERACTIVE(e->e_sendmode) #if _FFR_DM_ONE && (NotFirstDelivery || SM_DM_ONE != e->e_sendmode) #endif /* _FFR_DM_ONE */ @@ -3724,6 +3727,7 @@ smtp_data(smtp, e) _res.retrans = TimeOuts.res_retrans[RES_TO_FIRST]; #endif /* NAMED_BIND */ + for (ee = e; ee != NULL; ee = ee->e_sibling) { /* make sure we actually do delivery */ @@ -3767,18 +3771,18 @@ smtp_data(smtp, e) oldid = CurEnv->e_id; CurEnv->e_id = id; - /* issue success message */ + /* issue success message */ #if _FFR_MSG_ACCEPT - if (MessageAccept != NULL && *MessageAccept != '\0') - { - char msg[MAXLINE]; + if (MessageAccept != NULL && *MessageAccept != '\0') + { + char msg[MAXLINE]; - expand(MessageAccept, msg, sizeof(msg), e); - message("250 2.0.0 %s", msg); - } - else + expand(MessageAccept, msg, sizeof(msg), e); + message("250 2.0.0 %s", msg); + } + else #endif /* _FFR_MSG_ACCEPT */ - message("250 2.0.0 %s Message accepted for delivery", id); + message("250 2.0.0 %s Message accepted for delivery", id); CurEnv->e_id = oldid; /* if we just queued, poke it */ @@ -4687,7 +4691,8 @@ proxy_policy(conn, context, requested_user, rlen, auth_identity, alen, return SASL_FAIL; macdefine(&BlankEnvelope.e_macro, A_TEMP, - macid("{auth_authen}"), (char *) auth_identity); + macid("{auth_authen}"), + xtextify((char *) auth_identity, "=<>\")")); return SASL_OK; } diff --git a/contrib/sendmail/src/tls.c b/contrib/sendmail/src/tls.c index 70319944950..a57a05d3612 100644 --- a/contrib/sendmail/src/tls.c +++ b/contrib/sendmail/src/tls.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2006, 2008, 2009 Sendmail, Inc. and its suppliers. + * Copyright (c) 2000-2006, 2008, 2009, 2011 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set @@ -10,7 +10,7 @@ #include -SM_RCSID("@(#)$Id: tls.c,v 8.114 2009/08/10 15:11:09 ca Exp $") +SM_RCSID("@(#)$Id: tls.c,v 8.118 2011/03/07 23:20:47 ca Exp $") #if STARTTLS # include @@ -1168,7 +1168,7 @@ tls_get_info(ssl, srv, host, mac, certreq) MACROS_T *mac; bool certreq; { - SSL_CIPHER *c; + const SSL_CIPHER *c; int b, r; long verifyok; char *s, *who; @@ -1213,12 +1213,14 @@ tls_get_info(ssl, srv, host, mac, certreq) macdefine(mac, A_TEMP, macid("{cert_issuer}"), xtextify(buf, "<>\")")); +# define LL_BADCERT 8 + #define CHECK_X509_NAME(which) \ do { \ if (r == -1) \ { \ sm_strlcpy(buf, "BadCertificateUnknown", sizeof(buf)); \ - if (LogLevel > 7) \ + if (LogLevel > LL_BADCERT) \ sm_syslog(LOG_INFO, NOQID, \ "STARTTLS=%s, relay=%.100s, field=%s, status=failed to extract CN", \ who, \ diff --git a/contrib/sendmail/src/udb.c b/contrib/sendmail/src/udb.c index 29470e7c690..22b198e4e93 100644 --- a/contrib/sendmail/src/udb.c +++ b/contrib/sendmail/src/udb.c @@ -15,9 +15,9 @@ #include "map.h" #if USERDB -SM_RCSID("@(#)$Id: udb.c,v 8.164 2006/12/19 19:49:51 ca Exp $ (with USERDB)") +SM_RCSID("@(#)$Id: udb.c,v 8.165 2010/01/10 06:22:00 ca Exp $ (with USERDB)") #else /* USERDB */ -SM_RCSID("@(#)$Id: udb.c,v 8.164 2006/12/19 19:49:51 ca Exp $ (without USERDB)") +SM_RCSID("@(#)$Id: udb.c,v 8.165 2010/01/10 06:22:00 ca Exp $ (without USERDB)") #endif /* USERDB */ #if USERDB @@ -1219,7 +1219,7 @@ _udbx_close() # endif /* DB_VERSION_MAJOR < 2 */ } if (tTd(28, 1)) - sm_dprintf("_udbx_init: db->close(%s)\n", + sm_dprintf("_udbx_close: db->close(%s)\n", up->udb_dbname); # endif /* NEWDB */ } diff --git a/contrib/sendmail/src/usersmtp.c b/contrib/sendmail/src/usersmtp.c index 23278b0b59d..0de839e4221 100644 --- a/contrib/sendmail/src/usersmtp.c +++ b/contrib/sendmail/src/usersmtp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2006, 2008, 2009 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2006, 2008-2010 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -13,7 +13,7 @@ #include -SM_RCSID("@(#)$Id: usersmtp.c,v 8.473 2009/06/17 17:26:51 ca Exp $") +SM_RCSID("@(#)$Id: usersmtp.c,v 8.485 2010/07/23 21:09:38 ca Exp $") #include @@ -33,7 +33,6 @@ extern void sm_sasl_free __P((void *)); ** This protocol is described in RFC821. */ -#define REPLYCLASS(r) (((r) / 10) % 10) /* second digit of reply code */ #define SMTPCLOSING 421 /* "Service Shutting Down" */ #define ENHSCN(e, d) ((e) == NULL ? (d) : (e)) @@ -136,8 +135,7 @@ smtpinit(m, mci, e, onlyhelo) SmtpPhase = mci->mci_phase = "client greeting"; sm_setproctitle(true, e, "%s %s: %s", qid_printname(e), CurHostName, mci->mci_phase); - r = reply(m, mci, e, TimeOuts.to_initial, esmtp_check, NULL, - XS_DEFAULT); + r = reply(m, mci, e, TimeOuts.to_initial, esmtp_check, NULL, XS_GREET); if (r < 0) goto tempfail1; if (REPLYTYPE(r) == 4) @@ -183,7 +181,7 @@ tryhelo: r = reply(m, mci, e, bitnset(M_LMTP, m->m_flags) ? TimeOuts.to_lhlo : TimeOuts.to_helo, - helo_options, NULL, XS_DEFAULT); + helo_options, NULL, XS_EHLO); if (r < 0) goto tempfail1; else if (REPLYTYPE(r) == 5) @@ -336,7 +334,15 @@ str_union(s1, s2, rpool) l1 = strlen(s1); l2 = strlen(s2); rl = l1 + l2; - res = (char *) sm_rpool_malloc(rpool, rl + 2); + if (rl <= 0) + { + sm_syslog(LOG_WARNING, NOQID, + "str_union: stringlen1=%d, stringlen2=%d, sum=%d, status=overflow", + l1, l2, rl); + res = NULL; + } + else + res = (char *) sm_rpool_malloc(rpool, rl + 2); if (res == NULL) { if (l1 > l2) @@ -409,9 +415,7 @@ helo_options(line, firstline, m, mci, e) if (firstline) { -#if SASL - mci->mci_saslcap = NULL; -#endif /* SASL */ + mci_clr_extensions(mci); #if _FFR_IGNORE_EXT_ON_HELO logged = false; #endif /* _FFR_IGNORE_EXT_ON_HELO */ @@ -472,7 +476,8 @@ helo_options(line, firstline, m, mci, e) #if SASL else if (sm_strcasecmp(line, "auth") == 0) { - if (p != NULL && *p != '\0') + if (p != NULL && *p != '\0' && + !bitset(MCIF_AUTH2, mci->mci_flags)) { if (mci->mci_saslcap != NULL) { @@ -484,7 +489,7 @@ helo_options(line, firstline, m, mci, e) mci->mci_saslcap = str_union(mci->mci_saslcap, p, mci->mci_rpool); - mci->mci_flags |= MCIF_AUTH; + mci->mci_flags |= MCIF_AUTH2; } else { @@ -501,6 +506,9 @@ helo_options(line, firstline, m, mci, e) } } } + if (tTd(95, 5)) + sm_syslog(LOG_DEBUG, NOQID, "AUTH flags=%lx, mechs=%s", + mci->mci_flags, mci->mci_saslcap); } #endif /* SASL */ } @@ -1606,13 +1614,11 @@ attemptauth(m, mci, e, sai) (void) memset(&ssp, '\0', sizeof(ssp)); /* XXX should these be options settable via .cf ? */ - { - ssp.max_ssf = MaxSLBits; - ssp.maxbufsize = MAXOUTLEN; + ssp.max_ssf = MaxSLBits; + ssp.maxbufsize = MAXOUTLEN; # if 0 - ssp.security_flags = SASL_SEC_NOPLAINTEXT; + ssp.security_flags = SASL_SEC_NOPLAINTEXT; # endif /* 0 */ - } saslresult = sasl_setprop(mci->mci_conn, SASL_SEC_PROPS, &ssp); if (saslresult != SASL_OK) return EX_TEMPFAIL; @@ -2175,7 +2181,7 @@ smtpmailfrom(m, mci, e) SmtpPhase = mci->mci_phase = "client MAIL"; sm_setproctitle(true, e, "%s %s: %s", qid_printname(e), CurHostName, mci->mci_phase); - r = reply(m, mci, e, TimeOuts.to_mail, NULL, &enhsc, XS_DEFAULT); + r = reply(m, mci, e, TimeOuts.to_mail, NULL, &enhsc, XS_MAIL); if (r < 0) { /* communications failure */ @@ -2427,7 +2433,7 @@ smtprcptstat(to, m, mci, e) } enhsc = NULL; - r = reply(m, mci, e, TimeOuts.to_rcpt, NULL, &enhsc, XS_DEFAULT); + r = reply(m, mci, e, TimeOuts.to_rcpt, NULL, &enhsc, XS_RCPT); save_errno = errno; to->q_rstatus = sm_rpool_strdup_x(e->e_rpool, SmtpReplyBuffer); to->q_status = ENHSCN_RPOOL(enhsc, smtptodsn(r), e->e_rpool); @@ -2588,7 +2594,7 @@ smtpdata(m, mci, e, ctladdr, xstart) mci->mci_state = MCIS_DATA; sm_setproctitle(true, e, "%s %s: %s", qid_printname(e), CurHostName, mci->mci_phase); - r = reply(m, mci, e, TimeOuts.to_datainit, NULL, &enhsc, XS_DEFAULT); + r = reply(m, mci, e, TimeOuts.to_datainit, NULL, &enhsc, XS_DATA); if (r < 0 || REPLYTYPE(r) == 4) { if (r >= 0) @@ -2722,7 +2728,7 @@ smtpdata(m, mci, e, ctladdr, xstart) CurHostName, mci->mci_phase); if (bitnset(M_LMTP, m->m_flags)) return EX_OK; - r = reply(m, mci, e, TimeOuts.to_datafinal, NULL, &enhsc, XS_DEFAULT); + r = reply(m, mci, e, TimeOuts.to_datafinal, NULL, &enhsc, XS_EOM); if (r < 0) return EX_TEMPFAIL; if (mci->mci_state == MCIS_DATA) @@ -2807,7 +2813,7 @@ smtpgetstat(m, mci, e) enhsc = NULL; /* check for the results of the transaction */ - r = reply(m, mci, e, TimeOuts.to_datafinal, NULL, &enhsc, XS_DEFAULT); + r = reply(m, mci, e, TimeOuts.to_datafinal, NULL, &enhsc, XS_DATA2); if (r < 0) return EX_TEMPFAIL; xstat = EX_NOTSTICKY; @@ -2893,8 +2899,7 @@ smtpquit(m, mci, e) SmtpPhase = "client QUIT"; mci->mci_state = MCIS_QUITING; smtpmessage("QUIT", m, mci); - (void) reply(m, mci, e, TimeOuts.to_quit, NULL, NULL, - XS_DEFAULT); + (void) reply(m, mci, e, TimeOuts.to_quit, NULL, NULL, XS_QUIT); SuprErrs = oldSuprErrs; if (mci->mci_state == MCIS_CLOSED) goto end; @@ -3233,14 +3238,17 @@ reply(m, mci, e, timeout, pfunc, enhstat, rtype) if (pfunc != NULL) (*pfunc)(bufp, firstline, m, mci, e); - firstline = false; - /* decode the reply code */ r = atoi(bufp); /* extra semantics: 0xx codes are "informational" */ if (r < 100) + { + firstline = false; continue; + } + + firstline = false; /* if no continuation lines, return this line */ if (bufp[3] != '-') diff --git a/contrib/sendmail/src/version.c b/contrib/sendmail/src/version.c index cb94d0f2c57..4f156c26377 100644 --- a/contrib/sendmail/src/version.c +++ b/contrib/sendmail/src/version.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2009 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2011 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -13,6 +13,6 @@ #include -SM_RCSID("@(#)$Id: version.c,v 8.218 2009/12/23 04:43:09 ca Exp $") +SM_RCSID("@(#)$Id: version.c,v 8.227 2011/04/26 23:02:35 ca Exp $") -char Version[] = "8.14.4"; +char Version[] = "8.14.5"; diff --git a/etc/periodic/daily/800.scrub-zfs b/etc/periodic/daily/800.scrub-zfs index 7ad99fe797f..f1d74e3ff8c 100755 --- a/etc/periodic/daily/800.scrub-zfs +++ b/etc/periodic/daily/800.scrub-zfs @@ -46,7 +46,7 @@ case "$daily_scrub_zfs_enable" in esac # determine how many days shall be between scrubs - eval _pool_threshold=\${daily_scrub_zfs_${pool}_threshold} + eval _pool_threshold=\${daily_scrub_zfs_$(echo "${pool}"|tr -s "-" "_"|tr -s "." "_"|tr -s ":" "_")_threshold} if [ -z "${_pool_threshold}" ];then _pool_threshold=${daily_scrub_zfs_default_threshold} fi diff --git a/etc/sendmail/freebsd.mc b/etc/sendmail/freebsd.mc index 4bf41a56340..1e28c4724e1 100644 --- a/etc/sendmail/freebsd.mc +++ b/etc/sendmail/freebsd.mc @@ -66,12 +66,10 @@ dnl so this file will not serve as a database of the available servers. dnl For that, visit dnl http://www.google.com/Top/Computers/Internet/E-mail/Spam/Blacklists/ -dnl Uncomment to activate Realtime Blackhole List -dnl information available at http://www.mail-abuse.com/ -dnl NOTE: This is a subscription service as of July 31, 2001 -dnl FEATURE(dnsbl) +dnl Uncomment to activate your chosen DNS based blacklist +dnl FEATURE(dnsbl, `dnsbl.example.com') dnl Alternatively, you can provide your own server and rejection message: -dnl FEATURE(dnsbl, `blackholes.mail-abuse.org', ``"550 Mail from " $&{client_addr} " rejected, see http://mail-abuse.org/cgi-bin/lookup?" $&{client_addr}'') +dnl FEATURE(dnsbl, `dnsbl.example.com', ``"550 Mail from " $&{client_addr} " rejected'') dnl Dialup users should uncomment and define this appropriately dnl define(`SMART_HOST', `your.isp.mail.server') diff --git a/etc/sendmail/freebsd.submit.mc b/etc/sendmail/freebsd.submit.mc index 0fd8d63237a..c6ec6555359 100644 --- a/etc/sendmail/freebsd.submit.mc +++ b/etc/sendmail/freebsd.submit.mc @@ -25,4 +25,3 @@ define(`confBIND_OPTS', `WorkAroundBrokenAAAA')dnl dnl dnl If you use IPv6 only, change [127.0.0.1] to [IPv6:::1] FEATURE(`msp', `[127.0.0.1]')dnl - diff --git a/release/doc/en_US.ISO8859-1/relnotes/article.sgml b/release/doc/en_US.ISO8859-1/relnotes/article.sgml index f34a81df9a0..b40da22ac27 100644 --- a/release/doc/en_US.ISO8859-1/relnotes/article.sgml +++ b/release/doc/en_US.ISO8859-1/relnotes/article.sgml @@ -480,7 +480,7 @@ Figwort release to the Hydrangea release. sendmail has been updated from - 8.14.1 to 8.14.4. + 8.14.1 to 8.14.5. The timezone database has been updated from the tzdata2008h release to diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c index 6e494c7618a..7ad79d5dcb7 100644 --- a/sbin/camcontrol/camcontrol.c +++ b/sbin/camcontrol/camcontrol.c @@ -5044,13 +5044,13 @@ getdevid(struct cam_devitem *item) * then allocate that much memory and try again. */ retry: - ccb->ccb_h.func_code = XPT_GDEV_ADVINFO; + ccb->ccb_h.func_code = XPT_DEV_ADVINFO; ccb->ccb_h.flags = CAM_DIR_IN; - ccb->cgdai.flags = CGDAI_FLAG_PROTO; - ccb->cgdai.buftype = CGDAI_TYPE_SCSI_DEVID; - ccb->cgdai.bufsiz = item->device_id_len; + ccb->cdai.flags = 0; + ccb->cdai.buftype = CDAI_TYPE_SCSI_DEVID; + ccb->cdai.bufsiz = item->device_id_len; if (item->device_id_len != 0) - ccb->cgdai.buf = (uint8_t *)item->device_id; + ccb->cdai.buf = (uint8_t *)item->device_id; if (cam_send_ccb(dev, ccb) < 0) { warn("%s: error sending XPT_GDEV_ADVINFO CCB", __func__); @@ -5069,13 +5069,13 @@ retry: * This is our first time through. Allocate the buffer, * and then go back to get the data. */ - if (ccb->cgdai.provsiz == 0) { + if (ccb->cdai.provsiz == 0) { warnx("%s: invalid .provsiz field returned with " "XPT_GDEV_ADVINFO CCB", __func__); retval = 1; goto bailout; } - item->device_id_len = ccb->cgdai.provsiz; + item->device_id_len = ccb->cdai.provsiz; item->device_id = malloc(item->device_id_len); if (item->device_id == NULL) { warn("%s: unable to allocate %d bytes", __func__, @@ -5283,8 +5283,9 @@ findsasdevice(struct cam_devlist *devlist, uint64_t sasaddr) /* * XXX KDM look for LUN IDs as well? */ - item_addr = scsi_get_sas_addr(item->device_id, - item->device_id_len); + item_addr = scsi_get_devid(item->device_id, + item->device_id_len, + scsi_devid_is_sas_target); if (item_addr == NULL) continue; diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c index 2963b9f092d..408d77eaa22 100644 --- a/sbin/ifconfig/ifconfig.c +++ b/sbin/ifconfig/ifconfig.c @@ -908,7 +908,7 @@ unsetifdescr(const char *val, int value, int s, const struct afswtch *afp) #define IFCAPBITS \ "\020\1RXCSUM\2TXCSUM\3NETCONS\4VLAN_MTU\5VLAN_HWTAGGING\6JUMBO_MTU\7POLLING" \ "\10VLAN_HWCSUM\11TSO4\12TSO6\13LRO\14WOL_UCAST\15WOL_MCAST\16WOL_MAGIC" \ -"\21VLAN_HWFILTER\23VLAN_HWTSO\24LINKSTATE" +"\21VLAN_HWFILTER\23VLAN_HWTSO\24LINKSTATE\25NETMAP" /* * Print the status of the interface. If an address family was diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8 index fa9c54369c8..4a223203f7d 100644 --- a/sbin/ipfw/ipfw.8 +++ b/sbin/ipfw/ipfw.8 @@ -1,7 +1,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 30, 2011 +.Dd June 14, 2011 .Dt IPFW 8 .Os .Sh NAME @@ -2435,6 +2435,27 @@ Reset table of the packet aliasing engine on address change. Reverse the way libalias handles aliasing. .It Cm proxy_only Obey transparent proxy rules only, packet aliasing is not performed. +.It Cm skip_global +Skip instance in case of global state lookup (see below). +.El +.Pp +Some specials value can be supplied instead of +.Va nat_number: +.Bl -tag -width indent +.It Cm global +Looks up translation state in all configured nat instances. +If an entry is found, packet is aliased according to that entry. +If no entry was found in any of the instances, packet is passed unchanged, +and no new entry will be created. +See section +.Sx MULTIPLE INSTANCES +in +.Xr natd 8 +for more information. +.It Cm tablearg +Uses argument supplied in lookup table. See +.Sx LOOKUP TABLES +section below for more information on lookup tables. .El .Pp To let the packet continue after being (de)aliased, set the sysctl variable diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c index 3e85de3ef39..97d98a39f04 100644 --- a/sbin/ipfw/ipfw2.c +++ b/sbin/ipfw/ipfw2.c @@ -1121,8 +1121,11 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth) break; case O_NAT: - PRINT_UINT_ARG("nat ", cmd->arg1); - break; + if (cmd->arg1 != 0) + PRINT_UINT_ARG("nat ", cmd->arg1); + else + printf("nat global"); + break; case O_SETFIB: PRINT_UINT_ARG("setfib ", cmd->arg1); @@ -2738,9 +2741,14 @@ ipfw_add(char *av[]) break; case TOK_NAT: - action->opcode = O_NAT; - action->len = F_INSN_SIZE(ipfw_insn_nat); - goto chkarg; + action->opcode = O_NAT; + action->len = F_INSN_SIZE(ipfw_insn_nat); + if (_substrcmp(*av, "global") == 0) { + action->arg1 = 0; + av++; + break; + } else + goto chkarg; case TOK_QUEUE: action->opcode = O_QUEUE; diff --git a/sbin/ipfw/ipfw2.h b/sbin/ipfw/ipfw2.h index c9f86878920..9562f324432 100644 --- a/sbin/ipfw/ipfw2.h +++ b/sbin/ipfw/ipfw2.h @@ -178,6 +178,7 @@ enum tokens { TOK_DENY_INC, TOK_SAME_PORTS, TOK_UNREG_ONLY, + TOK_SKIP_GLOBAL, TOK_RESET_ADDR, TOK_ALIAS_REV, TOK_PROXY_ONLY, diff --git a/sbin/ipfw/nat.c b/sbin/ipfw/nat.c index 0331d383659..6f8c39f3e7a 100644 --- a/sbin/ipfw/nat.c +++ b/sbin/ipfw/nat.c @@ -53,6 +53,7 @@ static struct _s_x nat_params[] = { { "deny_in", TOK_DENY_INC }, { "same_ports", TOK_SAME_PORTS }, { "unreg_only", TOK_UNREG_ONLY }, + { "skip_global", TOK_SKIP_GLOBAL }, { "reset", TOK_RESET_ADDR }, { "reverse", TOK_ALIAS_REV }, { "proxy_only", TOK_PROXY_ONLY }, @@ -628,6 +629,9 @@ print_nat_config(unsigned char *buf) } else if (n->mode & PKT_ALIAS_SAME_PORTS) { printf(" same_ports"); n->mode &= ~PKT_ALIAS_SAME_PORTS; + } else if (n->mode & PKT_ALIAS_SKIP_GLOBAL) { + printf(" skip_global"); + n->mode &= ~PKT_ALIAS_SKIP_GLOBAL; } else if (n->mode & PKT_ALIAS_UNREGISTERED_ONLY) { printf(" unreg_only"); n->mode &= ~PKT_ALIAS_UNREGISTERED_ONLY; @@ -721,16 +725,18 @@ ipfw_config_nat(int ac, char **av) { struct cfg_nat *n; /* Nat instance configuration. */ int i, off, tok, ac1; - char *id, *buf, **av1; + char *id, *buf, **av1, *end; size_t len; av++; ac--; /* Nat id. */ - if (ac && isdigit(**av)) { - id = *av; - ac--; av++; - } else + if (ac == 0) errx(EX_DATAERR, "missing nat id"); + id = *av; + i = (int)strtol(id, &end, 0); + if (i <= 0 || *end != '\0') + errx(EX_DATAERR, "illegal nat id: %s", id); + av++; ac--; if (ac == 0) errx(EX_DATAERR, "missing option"); @@ -744,10 +750,11 @@ ipfw_config_nat(int ac, char **av) case TOK_IP: case TOK_IF: ac1--; av1++; - break; + break; case TOK_ALOG: case TOK_DENY_INC: case TOK_SAME_PORTS: + case TOK_SKIP_GLOBAL: case TOK_UNREG_ONLY: case TOK_RESET_ADDR: case TOK_ALIAS_REV: @@ -787,7 +794,6 @@ ipfw_config_nat(int ac, char **av) off = sizeof(*n); memset(buf, 0, len); n = (struct cfg_nat *)buf; - i = atoi(id); n->id = i; while (ac > 0) { @@ -820,6 +826,9 @@ ipfw_config_nat(int ac, char **av) case TOK_UNREG_ONLY: n->mode |= PKT_ALIAS_UNREGISTERED_ONLY; break; + case TOK_SKIP_GLOBAL: + n->mode |= PKT_ALIAS_SKIP_GLOBAL; + break; case TOK_RESET_ADDR: n->mode |= PKT_ALIAS_RESET_ON_ADDR_CHANGE; break; diff --git a/share/misc/committers-ports.dot b/share/misc/committers-ports.dot index f1a95bad19a..712590cbfec 100644 --- a/share/misc/committers-ports.dot +++ b/share/misc/committers-ports.dot @@ -166,6 +166,7 @@ skreuzer [label="Steven Kreuzer\nskreuzer@FreeBSD.org\n2009/03/25"] sobomax[label="Maxim Sobolev\nsobomax@FreeBSD.org\n2000/05/17"] stas [label="Stanislav Sedov\nstas@FreeBSD.org\n2006/09/18"] stefan [label="Stefan Walter\nstefan@FreeBSD.org\n2006/05/07"] +stephen [label="Stephen Montgomery-Smith\nstephen@FreeBSD.org\n2011/06/13"] sunpoet [label="Po-Chuan Hsieh\nsunpoet@FreeBSD.org\n2010/09/21"] sylvio [label="Sylvio Cesar Teixeira\nsylvio@FreeBSD.org\n2009/10/29"] swills [label="Steve Wills\nswills@FreeBSD.org\n2010/09/03"] @@ -259,6 +260,7 @@ flz -> romain gabor -> lippe gabor -> pgj +gabor -> stephen garga -> acm garga -> alepulver @@ -311,6 +313,7 @@ lioux -> pat lwhsu -> yzlin +maho -> stephen maho -> tota marcus -> ahze diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC index 7c860463ad3..4bfcfa328ce 100644 --- a/sys/amd64/conf/GENERIC +++ b/sys/amd64/conf/GENERIC @@ -295,6 +295,7 @@ options USB_DEBUG # enable debug msgs device uhci # UHCI PCI->USB interface device ohci # OHCI PCI->USB interface device ehci # EHCI PCI->USB interface (USB 2.0) +device xhci # XHCI PCI->USB interface (USB 3.0) device usb # USB Bus (required) #device udbp # USB Double Bulk Pipe devices (needs netgraph) device uhid # "Human Interface Devices" diff --git a/sys/cam/ata/ata_da.c b/sys/cam/ata/ata_da.c index 8e933022390..f1a94337675 100644 --- a/sys/cam/ata/ata_da.c +++ b/sys/cam/ata/ata_da.c @@ -812,6 +812,25 @@ adasysctlinit(void *context, int pending) cam_periph_release(periph); } +static int +adagetattr(struct bio *bp) +{ + int ret = -1; + struct cam_periph *periph; + + if (bp->bio_disk == NULL || bp->bio_disk->d_drv1) + return ENXIO; + periph = (struct cam_periph *)bp->bio_disk->d_drv1; + if (periph->path == NULL) + return ENXIO; + + ret = xpt_getattr(bp->bio_data, bp->bio_length, bp->bio_attribute, + periph->path); + if (ret == 0) + bp->bio_completed = bp->bio_length; + return ret; +} + static cam_status adaregister(struct cam_periph *periph, void *arg) { @@ -917,6 +936,7 @@ adaregister(struct cam_periph *periph, void *arg) softc->disk->d_open = adaopen; softc->disk->d_close = adaclose; softc->disk->d_strategy = adastrategy; + softc->disk->d_getattr = adagetattr; softc->disk->d_dump = adadump; softc->disk->d_name = "ada"; softc->disk->d_drv1 = periph; @@ -938,8 +958,6 @@ adaregister(struct cam_periph *periph, void *arg) ((softc->flags & ADA_FLAG_CAN_CFA) && !(softc->flags & ADA_FLAG_CAN_48BIT))) softc->disk->d_flags |= DISKFLAG_CANDELETE; - strlcpy(softc->disk->d_ident, cgd->serial_num, - MIN(sizeof(softc->disk->d_ident), cgd->serial_num_len + 1)); strlcpy(softc->disk->d_descr, cgd->ident_data.model, MIN(sizeof(softc->disk->d_descr), sizeof(cgd->ident_data.model))); softc->disk->d_hba_vendor = cpi.hba_vendor; diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h index 981a5ed6ada..ed2a8907689 100644 --- a/sys/cam/cam_ccb.h +++ b/sys/cam/cam_ccb.h @@ -144,8 +144,8 @@ typedef enum { /* Device statistics (error counts, etc.) */ XPT_FREEZE_QUEUE = 0x0d, /* Freeze device queue */ - XPT_GDEV_ADVINFO = 0x0e, - /* Advanced device information */ + XPT_DEV_ADVINFO = 0x0e, + /* Get/Set Device advanced information */ /* SCSI Control Functions: 0x10->0x1F */ XPT_ABORT = 0x10, /* Abort the specified CCB */ @@ -391,15 +391,24 @@ typedef enum { DEV_MATCH_TARGET = 0x002, DEV_MATCH_LUN = 0x004, DEV_MATCH_INQUIRY = 0x008, + DEV_MATCH_DEVID = 0x010, DEV_MATCH_ANY = 0x00f } dev_pattern_flags; +struct device_id_match_pattern { + uint8_t id_len; + uint8_t id[256]; +}; + struct device_match_pattern { - path_id_t path_id; - target_id_t target_id; - lun_id_t target_lun; - struct scsi_static_inquiry_pattern inq_pat; - dev_pattern_flags flags; + path_id_t path_id; + target_id_t target_id; + lun_id_t target_lun; + dev_pattern_flags flags; + union { + struct scsi_static_inquiry_pattern inq_pat; + struct device_id_match_pattern devid_pat; + } data; }; typedef enum { @@ -745,6 +754,7 @@ struct ccb_relsim { * Definitions for the asynchronous callback CCB fields. */ typedef enum { + AC_ADVINFO_CHANGED = 0x2000,/* Advance info might have changes */ AC_CONTRACT = 0x1000,/* A contractual callback */ AC_GETDEV_CHANGED = 0x800,/* Getdev info might have changed */ AC_INQ_CHANGED = 0x400,/* Inquiry info might have changed */ @@ -1094,19 +1104,20 @@ struct ccb_eng_exec { /* This structure must match SCSIIO size */ #define XPT_CCB_INVALID -1 /* for signaling a bad CCB to free */ /* - * CCB for getting advanced device information. This operates in a fashion + * CCB for working with advanced device information. This operates in a fashion * similar to XPT_GDEV_TYPE. Specify the target in ccb_h, the buffer * type requested, and provide a buffer size/buffer to write to. If the - * buffer is too small, the handler will set GDEVAI_FLAG_MORE. + * buffer is too small, provsiz will be larger than bufsiz. */ -struct ccb_getdev_advinfo { +struct ccb_dev_advinfo { struct ccb_hdr ccb_h; uint32_t flags; -#define CGDAI_FLAG_TRANSPORT 0x1 -#define CGDAI_FLAG_PROTO 0x2 +#define CDAI_FLAG_STORE 0x1 /* If set, action becomes store */ uint32_t buftype; /* IN: Type of data being requested */ /* NB: buftype is interpreted on a per-transport basis */ -#define CGDAI_TYPE_SCSI_DEVID 1 +#define CDAI_TYPE_SCSI_DEVID 1 +#define CDAI_TYPE_SERIAL_NUM 2 +#define CDAI_TYPE_PHYS_PATH 3 off_t bufsiz; /* IN: Size of external buffer */ #define CAM_SCSI_DEVID_MAXLEN 65536 /* length in buffer is an uint16_t */ off_t provsiz; /* OUT: Size required/used */ @@ -1151,7 +1162,7 @@ union ccb { struct ccb_rescan crcn; struct ccb_debug cdbg; struct ccb_ataio ataio; - struct ccb_getdev_advinfo cgdai; + struct ccb_dev_advinfo cdai; }; __BEGIN_DECLS diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c index dd51bca85ce..f63077220e6 100644 --- a/sys/cam/cam_periph.c +++ b/sys/cam/cam_periph.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -303,6 +304,38 @@ cam_periph_find(struct cam_path *path, char *name) return(NULL); } +/* + * Find a peripheral structure with the specified path, target, lun, + * and (optionally) type. If the name is NULL, this function will return + * the first peripheral driver that matches the specified path. + */ +int +cam_periph_list(struct cam_path *path, struct sbuf *sb) +{ + struct periph_driver **p_drv; + struct cam_periph *periph; + int count; + + count = 0; + xpt_lock_buses(); + for (p_drv = periph_drivers; *p_drv != NULL; p_drv++) { + + TAILQ_FOREACH(periph, &(*p_drv)->units, unit_links) { + if (xpt_path_comp(periph->path, path) != 0) + continue; + + if (sbuf_len(sb) != 0) + sbuf_cat(sb, ","); + + sbuf_printf(sb, "%s%d", periph->periph_name, + periph->unit_number); + count++; + } + } + xpt_unlock_buses(); + return (count); +} + cam_status cam_periph_acquire(struct cam_periph *periph) { @@ -654,12 +687,12 @@ cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo) dirs[1] = CAM_DIR_IN; numbufs = 2; break; - case XPT_GDEV_ADVINFO: - if (ccb->cgdai.bufsiz == 0) + case XPT_DEV_ADVINFO: + if (ccb->cdai.bufsiz == 0) return (0); - data_ptrs[0] = (uint8_t **)&ccb->cgdai.buf; - lengths[0] = ccb->cgdai.bufsiz; + data_ptrs[0] = (uint8_t **)&ccb->cdai.buf; + lengths[0] = ccb->cdai.bufsiz; dirs[0] = CAM_DIR_IN; numbufs = 1; @@ -813,9 +846,9 @@ cam_periph_unmapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo) data_ptrs[0] = &ccb->smpio.smp_request; data_ptrs[1] = &ccb->smpio.smp_response; break; - case XPT_GDEV_ADVINFO: + case XPT_DEV_ADVINFO: numbufs = min(mapinfo->num_bufs_used, 1); - data_ptrs[0] = (uint8_t **)&ccb->cgdai.buf; + data_ptrs[0] = (uint8_t **)&ccb->cdai.buf; break; default: /* allow ourselves to be swapped once again */ diff --git a/sys/cam/cam_periph.h b/sys/cam/cam_periph.h index 33e9f758435..58bfd7b2b18 100644 --- a/sys/cam/cam_periph.h +++ b/sys/cam/cam_periph.h @@ -142,6 +142,7 @@ cam_status cam_periph_alloc(periph_ctor_t *periph_ctor, char *name, cam_periph_type type, struct cam_path *, ac_callback_t *, ac_code, void *arg); struct cam_periph *cam_periph_find(struct cam_path *path, char *name); +int cam_periph_list(struct cam_path *, struct sbuf *); cam_status cam_periph_acquire(struct cam_periph *periph); void cam_periph_release(struct cam_periph *periph); void cam_periph_release_locked(struct cam_periph *periph); @@ -200,5 +201,12 @@ cam_periph_owned(struct cam_periph *periph) return (mtx_owned(periph->sim->mtx)); } +static __inline int +cam_periph_sleep(struct cam_periph *periph, void *chan, int priority, + const char *wmesg, int timo) +{ + return (msleep(chan, periph->sim->mtx, priority, wmesg, timo)); +} + #endif /* _KERNEL */ #endif /* _CAM_CAM_PERIPH_H */ diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c index 1ce205d2a64..f23407652a5 100644 --- a/sys/cam/cam_xpt.c +++ b/sys/cam/cam_xpt.c @@ -287,9 +287,6 @@ static xpt_targetfunc_t xptdeftargetfunc; static xpt_devicefunc_t xptdefdevicefunc; static xpt_periphfunc_t xptdefperiphfunc; static void xpt_finishconfig_task(void *context, int pending); -static int xpt_for_all_busses(xpt_busfunc_t *tr_func, void *arg); -static int xpt_for_all_devices(xpt_devicefunc_t *tr_func, - void *arg); static void xpt_dev_async_default(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target, @@ -1105,6 +1102,44 @@ xpt_announce_periph(struct cam_periph *periph, char *announce_string) periph->unit_number, announce_string); } +int +xpt_getattr(char *buf, size_t len, const char *attr, struct cam_path *path) +{ + int ret = -1; + struct ccb_dev_advinfo cdai; + + memset(&cdai, 0, sizeof(cdai)); + xpt_setup_ccb(&cdai.ccb_h, path, CAM_PRIORITY_NORMAL); + cdai.ccb_h.func_code = XPT_DEV_ADVINFO; + cdai.bufsiz = len; + + if (!strcmp(attr, "GEOM::ident")) + cdai.buftype = CDAI_TYPE_SERIAL_NUM; + else if (!strcmp(attr, "GEOM::physpath")) + cdai.buftype = CDAI_TYPE_PHYS_PATH; + else + goto out; + + cdai.buf = malloc(cdai.bufsiz, M_CAMXPT, M_NOWAIT|M_ZERO); + if (cdai.buf == NULL) { + ret = ENOMEM; + goto out; + } + xpt_action((union ccb *)&cdai); /* can only be synchronous */ + if ((cdai.ccb_h.status & CAM_DEV_QFRZN) != 0) + cam_release_devq(cdai.ccb_h.path, 0, 0, 0, FALSE); + if (cdai.provsiz == 0) + goto out; + ret = 0; + if (strlcpy(buf, cdai.buf, len) >= len) + ret = EFAULT; + +out: + if (cdai.buf != NULL) + free(cdai.buf, M_CAMXPT); + return ret; +} + static dev_match_ret xptbusmatch(struct dev_match_pattern *patterns, u_int num_patterns, struct cam_eb *bus) @@ -1241,6 +1276,7 @@ xptdevicematch(struct dev_match_pattern *patterns, u_int num_patterns, for (i = 0; i < num_patterns; i++) { struct device_match_pattern *cur_pattern; + struct scsi_vpd_device_id *device_id_page; /* * If the pattern in question isn't for a device node, we @@ -1255,22 +1291,17 @@ xptdevicematch(struct dev_match_pattern *patterns, u_int num_patterns, cur_pattern = &patterns[i].pattern.device_pattern; + /* Error out if mutually exclusive options are specified. */ + if ((cur_pattern->flags & (DEV_MATCH_INQUIRY|DEV_MATCH_DEVID)) + == (DEV_MATCH_INQUIRY|DEV_MATCH_DEVID)) + return(DM_RET_ERROR); + /* * If they want to match any device node, we give them any * device node. */ - if (cur_pattern->flags == DEV_MATCH_ANY) { - /* set the copy flag */ - retval |= DM_RET_COPY; - - - /* - * If we've already decided on an action, go ahead - * and return. - */ - if ((retval & DM_RET_ACTION_MASK) != DM_RET_NONE) - return(retval); - } + if (cur_pattern->flags == DEV_MATCH_ANY) + goto copy_dev_node; /* * Not sure why someone would do this... @@ -1292,11 +1323,22 @@ xptdevicematch(struct dev_match_pattern *patterns, u_int num_patterns, if (((cur_pattern->flags & DEV_MATCH_INQUIRY) != 0) && (cam_quirkmatch((caddr_t)&device->inq_data, - (caddr_t)&cur_pattern->inq_pat, - 1, sizeof(cur_pattern->inq_pat), + (caddr_t)&cur_pattern->data.inq_pat, + 1, sizeof(cur_pattern->data.inq_pat), scsi_static_inquiry_match) == NULL)) continue; + device_id_page = (struct scsi_vpd_device_id *)device->device_id; + if (((cur_pattern->flags & DEV_MATCH_DEVID) != 0) + && (device->device_id_len < SVPD_DEVICE_ID_HDR_LEN + || scsi_devid_match((uint8_t *)device_id_page->desc_list, + device->device_id_len + - SVPD_DEVICE_ID_HDR_LEN, + cur_pattern->data.devid_pat.id, + cur_pattern->data.devid_pat.id_len) != 0)) + continue; + +copy_dev_node: /* * If we get to this point, the user definitely wants * information on this device. So tell the caller to copy @@ -2889,6 +2931,8 @@ xpt_action_default(union ccb *start_ccb) case XPT_TERM_IO: case XPT_ENG_INQ: /* XXX Implement */ + printf("%s: CCB type %#x not supported\n", __func__, + start_ccb->ccb_h.func_code); start_ccb->ccb_h.status = CAM_PROVIDE_FAIL; if (start_ccb->ccb_h.func_code & XPT_FC_DEV_QUEUED) { xpt_done(start_ccb); @@ -3528,16 +3572,12 @@ xpt_path_string(struct cam_path *path, char *str, size_t str_len) path_id_t xpt_path_path_id(struct cam_path *path) { - mtx_assert(path->bus->sim->mtx, MA_OWNED); - return(path->bus->path_id); } target_id_t xpt_path_target_id(struct cam_path *path) { - mtx_assert(path->bus->sim->mtx, MA_OWNED); - if (path->target != NULL) return (path->target->target_id); else @@ -3547,8 +3587,6 @@ xpt_path_target_id(struct cam_path *path) lun_id_t xpt_path_lun_id(struct cam_path *path) { - mtx_assert(path->bus->sim->mtx, MA_OWNED); - if (path->device != NULL) return (path->device->lun_id); else @@ -4242,7 +4280,8 @@ xpt_alloc_target(struct cam_eb *bus, target_id_t target_id) { struct cam_et *target; - target = (struct cam_et *)malloc(sizeof(*target), M_CAMXPT, M_NOWAIT); + target = (struct cam_et *)malloc(sizeof(*target), M_CAMXPT, + M_NOWAIT|M_ZERO); if (target != NULL) { struct cam_et *cur_target; @@ -4330,7 +4369,7 @@ xpt_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id) device = NULL; } else { device = (struct cam_ed *)malloc(sizeof(*device), - M_CAMXPT, M_NOWAIT); + M_CAMXPT, M_NOWAIT|M_ZERO); } if (device != NULL) { @@ -4676,27 +4715,29 @@ xpt_register_async(int event, ac_callback_t *cbfunc, void *cbarg, csa.callback_arg = cbarg; xpt_action((union ccb *)&csa); status = csa.ccb_h.status; + if (xptpath) { xpt_free_path(path); mtx_unlock(&xsoftc.xpt_lock); - - if ((status == CAM_REQ_CMP) && - (csa.event_enable & AC_FOUND_DEVICE)) { - /* - * Get this peripheral up to date with all - * the currently existing devices. - */ - xpt_for_all_devices(xptsetasyncfunc, &csa); - } - if ((status == CAM_REQ_CMP) && - (csa.event_enable & AC_PATH_REGISTERED)) { - /* - * Get this peripheral up to date with all - * the currently existing busses. - */ - xpt_for_all_busses(xptsetasyncbusfunc, &csa); - } } + + if ((status == CAM_REQ_CMP) && + (csa.event_enable & AC_FOUND_DEVICE)) { + /* + * Get this peripheral up to date with all + * the currently existing devices. + */ + xpt_for_all_devices(xptsetasyncfunc, &csa); + } + if ((status == CAM_REQ_CMP) && + (csa.event_enable & AC_PATH_REGISTERED)) { + /* + * Get this peripheral up to date with all + * the currently existing busses. + */ + xpt_for_all_busses(xptsetasyncbusfunc, &csa); + } + return (status); } @@ -4852,8 +4893,10 @@ camisr_runqueue(void *V_queue) if ((dev->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 && (--dev->tag_delay_count == 0)) xpt_start_tags(ccb_h->path); - if (!device_is_send_queued(dev)) - xpt_schedule_dev_sendq(ccb_h->path->bus, dev); + if (!device_is_send_queued(dev)) { + runq = xpt_schedule_dev_sendq(ccb_h->path->bus, + dev); + } } if (ccb_h->status & CAM_RELEASE_SIMQ) { diff --git a/sys/cam/cam_xpt.h b/sys/cam/cam_xpt.h index 9355be4f222..f7d9b428cb7 100644 --- a/sys/cam/cam_xpt.h +++ b/sys/cam/cam_xpt.h @@ -103,6 +103,8 @@ cam_status xpt_create_path_unlocked(struct cam_path **new_path_ptr, struct cam_periph *perph, path_id_t path_id, target_id_t target_id, lun_id_t lun_id); +int xpt_getattr(char *buf, size_t len, const char *attr, + struct cam_path *path); void xpt_free_path(struct cam_path *path); int xpt_path_comp(struct cam_path *path1, struct cam_path *path2); diff --git a/sys/cam/cam_xpt_internal.h b/sys/cam/cam_xpt_internal.h index f485e37f489..b6e8f66399e 100644 --- a/sys/cam/cam_xpt_internal.h +++ b/sys/cam/cam_xpt_internal.h @@ -97,6 +97,8 @@ struct cam_ed { uint8_t supported_vpds_len; uint32_t device_id_len; uint8_t *device_id; + uint8_t physpath_len; + uint8_t *physpath; /* physical path string form */ struct ata_params ident_data; u_int8_t inq_flags; /* * Current settings for inquiry flags. diff --git a/sys/cam/scsi/scsi_all.c b/sys/cam/scsi/scsi_all.c index 7ededa17f5e..7361c42f0bd 100644 --- a/sys/cam/scsi/scsi_all.c +++ b/sys/cam/scsi/scsi_all.c @@ -3552,32 +3552,63 @@ scsi_calc_syncparam(u_int period) return (period/400); } -uint8_t * -scsi_get_sas_addr(struct scsi_vpd_device_id *id, uint32_t len) +int +scsi_devid_is_naa_ieee_reg(uint8_t *bufp) { - uint8_t *bufp, *buf_end; struct scsi_vpd_id_descriptor *descr; struct scsi_vpd_id_naa_basic *naa; - bufp = buf_end = (uint8_t *)id; - bufp += SVPD_DEVICE_ID_HDR_LEN; - buf_end += len; - while (bufp < buf_end) { - descr = (struct scsi_vpd_id_descriptor *)bufp; - bufp += SVPD_DEVICE_ID_DESC_HDR_LEN; - /* Right now, we only care about SAS NAA IEEE Reg addrs */ - if (((descr->id_type & SVPD_ID_PIV) != 0) - && (descr->proto_codeset >> SVPD_ID_PROTO_SHIFT) == - SCSI_PROTO_SAS - && (descr->id_type & SVPD_ID_TYPE_MASK) == SVPD_ID_TYPE_NAA){ - naa = (struct scsi_vpd_id_naa_basic *)bufp; - if ((naa->naa >> 4) == SVPD_ID_NAA_IEEE_REG) - return bufp; - } - bufp += descr->length; + descr = (struct scsi_vpd_id_descriptor *)bufp; + naa = (struct scsi_vpd_id_naa_basic *)descr->identifier; + if ((descr->id_type & SVPD_ID_TYPE_MASK) != SVPD_ID_TYPE_NAA) + return 0; + if (descr->length < sizeof(struct scsi_vpd_id_naa_ieee_reg)) + return 0; + if ((naa->naa >> SVPD_ID_NAA_NAA_SHIFT) != SVPD_ID_NAA_IEEE_REG) + return 0; + return 1; +} + +int +scsi_devid_is_sas_target(uint8_t *bufp) +{ + struct scsi_vpd_id_descriptor *descr; + + descr = (struct scsi_vpd_id_descriptor *)bufp; + if (!scsi_devid_is_naa_ieee_reg(bufp)) + return 0; + if ((descr->id_type & SVPD_ID_PIV) == 0) /* proto field reserved */ + return 0; + if ((descr->proto_codeset >> SVPD_ID_PROTO_SHIFT) != SCSI_PROTO_SAS) + return 0; + return 1; +} + +uint8_t * +scsi_get_devid(struct scsi_vpd_device_id *id, uint32_t page_len, + scsi_devid_checkfn_t ck_fn) +{ + struct scsi_vpd_id_descriptor *desc; + uint8_t *page_end; + uint8_t *desc_buf_end; + + page_end = (uint8_t *)id + page_len; + if (page_end < id->desc_list) + return (NULL); + + desc_buf_end = MIN(id->desc_list + scsi_2btoul(id->length), page_end); + + for (desc = (struct scsi_vpd_id_descriptor *)id->desc_list; + desc->identifier <= desc_buf_end + && desc->identifier + desc->length <= desc_buf_end; + desc = (struct scsi_vpd_id_descriptor *)(desc->identifier + + desc->length)) { + + if (ck_fn == NULL || ck_fn((uint8_t *)desc) != 0) + return (desc->identifier); } - return NULL; + return (NULL); } void @@ -4174,6 +4205,77 @@ scsi_read_write(struct ccb_scsiio *csio, u_int32_t retries, timeout); } +void +scsi_receive_diagnostic_results(struct ccb_scsiio *csio, u_int32_t retries, + void (*cbfcnp)(struct cam_periph *, union ccb*), + uint8_t tag_action, int pcv, uint8_t page_code, + uint8_t *data_ptr, uint16_t allocation_length, + uint8_t sense_len, uint32_t timeout) +{ + struct scsi_receive_diag *scsi_cmd; + + scsi_cmd = (struct scsi_receive_diag *)&csio->cdb_io.cdb_bytes; + memset(scsi_cmd, 0, sizeof(*scsi_cmd)); + scsi_cmd->opcode = RECEIVE_DIAGNOSTIC; + if (pcv) { + scsi_cmd->byte2 |= SRD_PCV; + scsi_cmd->page_code = page_code; + } + scsi_ulto2b(allocation_length, scsi_cmd->length); + + cam_fill_csio(csio, + retries, + cbfcnp, + /*flags*/CAM_DIR_IN, + tag_action, + data_ptr, + allocation_length, + sense_len, + sizeof(*scsi_cmd), + timeout); +} + +void +scsi_send_diagnostic(struct ccb_scsiio *csio, u_int32_t retries, + void (*cbfcnp)(struct cam_periph *, union ccb *), + uint8_t tag_action, int unit_offline, int device_offline, + int self_test, int page_format, int self_test_code, + uint8_t *data_ptr, uint16_t param_list_length, + uint8_t sense_len, uint32_t timeout) +{ + struct scsi_send_diag *scsi_cmd; + + scsi_cmd = (struct scsi_send_diag *)&csio->cdb_io.cdb_bytes; + memset(scsi_cmd, 0, sizeof(*scsi_cmd)); + scsi_cmd->opcode = SEND_DIAGNOSTIC; + + /* + * The default self-test mode control and specific test + * control are mutually exclusive. + */ + if (self_test) + self_test_code = SSD_SELF_TEST_CODE_NONE; + + scsi_cmd->byte2 = ((self_test_code << SSD_SELF_TEST_CODE_SHIFT) + & SSD_SELF_TEST_CODE_MASK) + | (unit_offline ? SSD_UNITOFFL : 0) + | (device_offline ? SSD_DEVOFFL : 0) + | (self_test ? SSD_SELFTEST : 0) + | (page_format ? SSD_PF : 0); + scsi_ulto2b(param_list_length, scsi_cmd->length); + + cam_fill_csio(csio, + retries, + cbfcnp, + /*flags*/param_list_length ? CAM_DIR_OUT : CAM_DIR_NONE, + tag_action, + data_ptr, + param_list_length, + sense_len, + sizeof(*scsi_cmd), + timeout); +} + void scsi_start_stop(struct ccb_scsiio *csio, u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *), @@ -4206,7 +4308,6 @@ scsi_start_stop(struct ccb_scsiio *csio, u_int32_t retries, sense_len, sizeof(*scsi_cmd), timeout); - } @@ -4264,6 +4365,66 @@ scsi_static_inquiry_match(caddr_t inqbuffer, caddr_t table_entry) return (-1); } +/** + * Compare two buffers of vpd device descriptors for a match. + * + * \param lhs Pointer to first buffer of descriptors to compare. + * \param lhs_len The length of the first buffer. + * \param rhs Pointer to second buffer of descriptors to compare. + * \param rhs_len The length of the second buffer. + * + * \return 0 on a match, -1 otherwise. + * + * Treat rhs and lhs as arrays of vpd device id descriptors. Walk lhs matching + * agains each element in rhs until all data are exhausted or we have found + * a match. + */ +int +scsi_devid_match(uint8_t *lhs, size_t lhs_len, uint8_t *rhs, size_t rhs_len) +{ + struct scsi_vpd_id_descriptor *lhs_id; + struct scsi_vpd_id_descriptor *lhs_last; + struct scsi_vpd_id_descriptor *rhs_last; + uint8_t *lhs_end; + uint8_t *rhs_end; + + lhs_end = lhs + lhs_len; + rhs_end = rhs + rhs_len; + + /* + * rhs_last and lhs_last are the last posible position of a valid + * descriptor assuming it had a zero length identifier. We use + * these variables to insure we can safely dereference the length + * field in our loop termination tests. + */ + lhs_last = (struct scsi_vpd_id_descriptor *) + (lhs_end - __offsetof(struct scsi_vpd_id_descriptor, identifier)); + rhs_last = (struct scsi_vpd_id_descriptor *) + (rhs_end - __offsetof(struct scsi_vpd_id_descriptor, identifier)); + + lhs_id = (struct scsi_vpd_id_descriptor *)lhs; + while (lhs_id <= lhs_last + && (lhs_id->identifier + lhs_id->length) <= lhs_end) { + struct scsi_vpd_id_descriptor *rhs_id; + + rhs_id = (struct scsi_vpd_id_descriptor *)rhs; + while (rhs_id <= rhs_last + && (rhs_id->identifier + rhs_id->length) <= rhs_end) { + + if (rhs_id->length == lhs_id->length + && memcmp(rhs_id->identifier, lhs_id->identifier, + rhs_id->length) == 0) + return (0); + + rhs_id = (struct scsi_vpd_id_descriptor *) + (rhs_id->identifier + rhs_id->length); + } + lhs_id = (struct scsi_vpd_id_descriptor *) + (lhs_id->identifier + lhs_id->length); + } + return (-1); +} + #ifdef _KERNEL static void init_scsi_delay(void) diff --git a/sys/cam/scsi/scsi_all.h b/sys/cam/scsi/scsi_all.h index 0a7a58fcb31..93b11d5a680 100644 --- a/sys/cam/scsi/scsi_all.h +++ b/sys/cam/scsi/scsi_all.h @@ -115,6 +115,7 @@ struct scsi_request_sense { u_int8_t opcode; u_int8_t byte2; +#define SRS_DESC 0x01 u_int8_t unused[2]; u_int8_t length; u_int8_t control; @@ -128,17 +129,33 @@ struct scsi_test_unit_ready u_int8_t control; }; -struct scsi_send_diag -{ - u_int8_t opcode; - u_int8_t byte2; -#define SSD_UOL 0x01 -#define SSD_DOL 0x02 -#define SSD_SELFTEST 0x04 -#define SSD_PF 0x10 - u_int8_t unused[1]; - u_int8_t paramlen[2]; - u_int8_t control; +struct scsi_receive_diag { + uint8_t opcode; + uint8_t byte2; +#define SRD_PCV 0x01 + uint8_t page_code; + uint8_t length[2]; + uint8_t control; +}; + +struct scsi_send_diag { + uint8_t opcode; + uint8_t byte2; +#define SSD_UNITOFFL 0x01 +#define SSD_DEVOFFL 0x02 +#define SSD_SELFTEST 0x04 +#define SSD_PF 0x10 +#define SSD_SELF_TEST_CODE_MASK 0xE0 +#define SSD_SELF_TEST_CODE_SHIFT 5 +#define SSD_SELF_TEST_CODE_NONE 0x00 +#define SSD_SELF_TEST_CODE_BG_SHORT 0x01 +#define SSD_SELF_TEST_CODE_BG_EXTENDED 0x02 +#define SSD_SELF_TEST_CODE_BG_ABORT 0x04 +#define SSD_SELF_TEST_CODE_FG_SHORT 0x05 +#define SSD_SELF_TEST_CODE_FG_EXTENDED 0x06 + uint8_t reserved; + uint8_t length[2]; + uint8_t control; }; struct scsi_sense @@ -894,11 +911,12 @@ struct scsi_vpd_id_naa_basic uint8_t naa : 4; uint8_t naa_desig : 4; */ +#define SVPD_ID_NAA_NAA_SHIFT 4 #define SVPD_ID_NAA_IEEE_EXT 0x02 #define SVPD_ID_NAA_LOCAL_REG 0x03 #define SVPD_ID_NAA_IEEE_REG 0x05 #define SVPD_ID_NAA_IEEE_REG_EXT 0x06 - uint8_t naa_data[0]; + uint8_t naa_data[]; }; struct scsi_vpd_id_naa_ieee_extended_id @@ -1322,7 +1340,12 @@ void scsi_print_inquiry(struct scsi_inquiry_data *inq_data); u_int scsi_calc_syncsrate(u_int period_factor); u_int scsi_calc_syncparam(u_int period); -uint8_t * scsi_get_sas_addr(struct scsi_vpd_device_id *id, uint32_t len); + +typedef int (*scsi_devid_checkfn_t)(uint8_t *); +int scsi_devid_is_naa_ieee_reg(uint8_t *bufp); +int scsi_devid_is_sas_target(uint8_t *bufp); +uint8_t * scsi_get_devid(struct scsi_vpd_device_id *id, uint32_t len, + scsi_devid_checkfn_t ck_fn); void scsi_test_unit_ready(struct ccb_scsiio *csio, u_int32_t retries, void (*cbfcnp)(struct cam_periph *, @@ -1439,6 +1462,22 @@ void scsi_synchronize_cache(struct ccb_scsiio *csio, u_int32_t begin_lba, u_int16_t lb_count, u_int8_t sense_len, u_int32_t timeout); +void scsi_receive_diagnostic_results(struct ccb_scsiio *csio, u_int32_t retries, + void (*cbfcnp)(struct cam_periph *, + union ccb*), + uint8_t tag_action, int pcv, + uint8_t page_code, uint8_t *data_ptr, + uint16_t allocation_length, + uint8_t sense_len, uint32_t timeout); + +void scsi_send_diagnostic(struct ccb_scsiio *csio, u_int32_t retries, + void (*cbfcnp)(struct cam_periph *, union ccb *), + uint8_t tag_action, int unit_offline, + int device_offline, int self_test, int page_format, + int self_test_code, uint8_t *data_ptr, + uint16_t param_list_length, uint8_t sense_len, + uint32_t timeout); + void scsi_read_write(struct ccb_scsiio *csio, u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, int readop, u_int8_t byte2, @@ -1455,6 +1494,8 @@ void scsi_start_stop(struct ccb_scsiio *csio, u_int32_t retries, int scsi_inquiry_match(caddr_t inqbuffer, caddr_t table_entry); int scsi_static_inquiry_match(caddr_t inqbuffer, caddr_t table_entry); +int scsi_devid_match(uint8_t *rhs, size_t rhs_len, + uint8_t *lhs, size_t lhs_len); static __inline void scsi_extract_sense(struct scsi_sense_data *sense, int *error_code, int *sense_key, diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c index 97298786fa1..a4363186a0b 100644 --- a/sys/cam/scsi/scsi_da.c +++ b/sys/cam/scsi/scsi_da.c @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #endif /* _KERNEL */ @@ -727,7 +728,8 @@ daclose(struct disk *dp) softc = (struct da_softc *)periph->softc; - if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) { + if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0 + && (softc->flags & DA_FLAG_PACK_INVALID) == 0) { union ccb *ccb; ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL); @@ -932,6 +934,25 @@ dadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t leng return (0); } +static int +dagetattr(struct bio *bp) +{ + int ret = -1; + struct cam_periph *periph; + + if (bp->bio_disk == NULL || bp->bio_disk->d_drv1 == NULL) + return ENXIO; + periph = (struct cam_periph *)bp->bio_disk->d_drv1; + if (periph->path == NULL) + return ENXIO; + + ret = xpt_getattr(bp->bio_data, bp->bio_length, bp->bio_attribute, + periph->path); + if (ret == 0) + bp->bio_completed = bp->bio_length; + return ret; +} + static void dainit(void) { @@ -977,7 +998,8 @@ daoninvalidate(struct cam_periph *periph) bioq_flush(&softc->bio_queue, NULL, ENXIO); disk_gone(softc->disk); - xpt_print(periph->path, "lost device\n"); + xpt_print(periph->path, "lost device - %d outstanding\n", + softc->outstanding_cmds); } static void @@ -1044,6 +1066,20 @@ daasync(void *callback_arg, u_int32_t code, && status != CAM_REQ_INPROG) printf("daasync: Unable to attach to new device " "due to status 0x%x\n", status); + return; + } + case AC_ADVINFO_CHANGED: + { + uintptr_t buftype; + + buftype = (uintptr_t)arg; + if (buftype == CDAI_TYPE_PHYS_PATH) { + struct da_softc *softc; + + softc = periph->softc; + disk_attr_changed(softc->disk, "GEOM::physpath", + M_NOWAIT); + } break; } case AC_SENT_BDR: @@ -1060,12 +1096,12 @@ daasync(void *callback_arg, u_int32_t code, softc->flags |= DA_FLAG_RETRY_UA; LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le) ccbh->ccb_state |= DA_CCB_RETRY_UA; - /* FALLTHROUGH*/ - } - default: - cam_periph_async(periph, code, path, arg); break; } + default: + break; + } + cam_periph_async(periph, code, path, arg); } static void @@ -1230,17 +1266,6 @@ daregister(struct cam_periph *periph, void *arg) TASK_INIT(&softc->sysctl_task, 0, dasysctlinit, periph); - /* - * Add async callbacks for bus reset and - * bus device reset calls. I don't bother - * checking if this fails as, in most cases, - * the system will function just fine without - * them and the only alternative would be to - * not attach the device on failure. - */ - xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE, - daasync, periph, periph->path); - /* * Take an exclusive refcount on the periph while dastart is called * to finish the probe. The reference will be dropped in dadone at @@ -1301,6 +1326,7 @@ daregister(struct cam_periph *periph, void *arg) softc->disk->d_close = daclose; softc->disk->d_strategy = dastrategy; softc->disk->d_dump = dadump; + softc->disk->d_getattr = dagetattr; softc->disk->d_name = "da"; softc->disk->d_drv1 = periph; if (cpi.maxio == 0) @@ -1313,8 +1339,6 @@ daregister(struct cam_periph *periph, void *arg) softc->disk->d_flags = 0; if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE; - strlcpy(softc->disk->d_ident, cgd->serial_num, - MIN(sizeof(softc->disk->d_ident), cgd->serial_num_len + 1)); cam_strvis(softc->disk->d_descr, cgd->inq_data.vendor, sizeof(cgd->inq_data.vendor), sizeof(softc->disk->d_descr)); strlcat(softc->disk->d_descr, " ", sizeof(softc->disk->d_descr)); @@ -1328,6 +1352,25 @@ daregister(struct cam_periph *periph, void *arg) disk_create(softc->disk, DISK_VERSION); mtx_lock(periph->sim->mtx); + /* + * Add async callbacks for events of interest. + * I don't bother checking if this fails as, + * in most cases, the system will function just + * fine without them and the only alternative + * would be to not attach the device on failure. + */ + xpt_register_async(AC_SENT_BDR | AC_BUS_RESET + | AC_LOST_DEVICE | AC_ADVINFO_CHANGED, + daasync, periph, periph->path); + + /* + * Emit an attribute changed notification just in case + * physical path information arrived before our async + * event handler was registered, but after anyone attaching + * to our disk device polled it. + */ + disk_attr_changed(softc->disk, "GEOM::physpath", M_NOWAIT); + xpt_schedule(periph, CAM_PRIORITY_DEV); return(CAM_REQ_CMP); @@ -1558,7 +1601,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb) if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { int error; int sf; - + if ((csio->ccb_h.ccb_state & DA_CCB_RETRY_UA) != 0) sf = SF_RETRY_UA; else @@ -1573,8 +1616,17 @@ dadone(struct cam_periph *periph, union ccb *done_ccb) return; } if (error != 0) { + int queued_error; - if (error == ENXIO) { + /* + * return all queued I/O with EIO, so that + * the client can retry these I/Os in the + * proper order should it attempt to recover. + */ + queued_error = EIO; + + if (error == ENXIO + && (softc->flags & DA_FLAG_PACK_INVALID)== 0) { /* * Catastrophic error. Mark our pack as * invalid. @@ -1586,14 +1638,10 @@ dadone(struct cam_periph *periph, union ccb *done_ccb) xpt_print(periph->path, "Invalidating pack\n"); softc->flags |= DA_FLAG_PACK_INVALID; + queued_error = ENXIO; } - - /* - * return all queued I/O with EIO, so that - * the client can retry these I/Os in the - * proper order should it attempt to recover. - */ - bioq_flush(&softc->bio_queue, NULL, EIO); + bioq_flush(&softc->bio_queue, NULL, + queued_error); bp->bio_error = error; bp->bio_resid = bp->bio_bcount; bp->bio_flags |= BIO_ERROR; @@ -1626,6 +1674,11 @@ dadone(struct cam_periph *periph, union ccb *done_ccb) if (softc->outstanding_cmds == 0) softc->flags |= DA_FLAG_WENT_IDLE; + if ((softc->flags & DA_FLAG_PACK_INVALID) != 0) { + xpt_print(periph->path, "oustanding %d\n", + softc->outstanding_cmds); + } + biodone(bp); break; } diff --git a/sys/cam/scsi/scsi_pass.c b/sys/cam/scsi/scsi_pass.c index e7ecb35d0fd..a124468a56d 100644 --- a/sys/cam/scsi/scsi_pass.c +++ b/sys/cam/scsi/scsi_pass.c @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -70,12 +71,14 @@ typedef enum { #define ccb_bp ppriv_ptr1 struct pass_softc { - pass_state state; - pass_flags flags; - u_int8_t pd_type; - union ccb saved_ccb; - struct devstat *device_stats; - struct cdev *dev; + pass_state state; + pass_flags flags; + u_int8_t pd_type; + union ccb saved_ccb; + struct devstat *device_stats; + struct cdev *dev; + struct cdev *alias_dev; + struct task add_physpath_task; }; @@ -88,6 +91,7 @@ static periph_ctor_t passregister; static periph_oninv_t passoninvalidate; static periph_dtor_t passcleanup; static periph_start_t passstart; +static void pass_add_physpath(void *context, int pending); static void passasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg); static void passdone(struct cam_periph *periph, @@ -168,16 +172,44 @@ passcleanup(struct cam_periph *periph) if (bootverbose) xpt_print(periph->path, "removing device entry\n"); devstat_remove_entry(softc->device_stats); + cam_periph_unlock(periph); + taskqueue_drain(taskqueue_thread, &softc->add_physpath_task); + /* * passcleanup() is indirectly a d_close method via passclose, * so using destroy_dev(9) directly can result in deadlock. */ destroy_dev_sched(softc->dev); cam_periph_lock(periph); + free(softc, M_DEVBUF); } +static void +pass_add_physpath(void *context, int pending) +{ + struct cam_periph *periph; + struct pass_softc *softc; + char *physpath; + + /* + * If we have one, create a devfs alias for our + * physical path. + */ + periph = context; + softc = periph->softc; + physpath = malloc(MAXPATHLEN, M_DEVBUF, M_WAITOK); + if (xpt_getattr(physpath, MAXPATHLEN, + "GEOM::physpath", periph->path) == 0 + && strlen(physpath) != 0) { + + make_dev_physpath_alias(MAKEDEV_WAITOK, &softc->alias_dev, + softc->dev, softc->alias_dev, physpath); + } + free(physpath, M_DEVBUF); +} + static void passasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg) @@ -219,6 +251,20 @@ passasync(void *callback_arg, u_int32_t code, break; } + case AC_ADVINFO_CHANGED: + { + uintptr_t buftype; + + buftype = (uintptr_t)arg; + if (buftype == CDAI_TYPE_PHYS_PATH) { + struct pass_softc *softc; + + softc = (struct pass_softc *)periph->softc; + taskqueue_enqueue(taskqueue_thread, + &softc->add_physpath_task); + } + break; + } default: cam_periph_async(periph, code, path, arg); break; @@ -292,11 +338,22 @@ passregister(struct cam_periph *periph, void *arg) mtx_lock(periph->sim->mtx); softc->dev->si_drv1 = periph; + TASK_INIT(&softc->add_physpath_task, /*priority*/0, + pass_add_physpath, periph); + /* - * Add an async callback so that we get - * notified if this device goes away. + * See if physical path information is already available. */ - xpt_register_async(AC_LOST_DEVICE, passasync, periph, periph->path); + taskqueue_enqueue(taskqueue_thread, &softc->add_physpath_task); + + /* + * Add an async callback so that we get notified if + * this device goes away or its physical path + * (stored in the advanced info data of the EDT) has + * changed. + */ + xpt_register_async(AC_LOST_DEVICE | AC_ADVINFO_CHANGED, + passasync, periph, periph->path); if (bootverbose) xpt_announce_periph(periph, NULL); @@ -548,8 +605,8 @@ passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb) && ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)) || (ccb->ccb_h.func_code == XPT_DEV_MATCH) || (ccb->ccb_h.func_code == XPT_SMP_IO) - || ((ccb->ccb_h.func_code == XPT_GDEV_ADVINFO) - && (ccb->cgdai.bufsiz > 0)))) { + || ((ccb->ccb_h.func_code == XPT_DEV_ADVINFO) + && (ccb->cdai.bufsiz > 0)))) { bzero(&mapinfo, sizeof(mapinfo)); diff --git a/sys/cam/scsi/scsi_xpt.c b/sys/cam/scsi/scsi_xpt.c index 2a38128da9d..1b507cae125 100644 --- a/sys/cam/scsi/scsi_xpt.c +++ b/sys/cam/scsi/scsi_xpt.c @@ -542,6 +542,7 @@ static const int scsi_quirk_table_size = static cam_status proberegister(struct cam_periph *periph, void *arg); static void probeschedule(struct cam_periph *probe_periph); +static int device_has_vpd(struct cam_ed *device, uint8_t page_id); static void probestart(struct cam_periph *periph, union ccb *start_ccb); static void proberequestdefaultnegotiation(struct cam_periph *periph); static int proberequestbackoff(struct cam_periph *periph, @@ -1460,7 +1461,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb) path->device->device_id = (uint8_t *)devid; } } else if (cam_periph_error(done_ccb, 0, - SF_RETRY_UA|SF_NO_PRINT, + SF_RETRY_UA, &softc->saved_ccb) == ERESTART) { return; } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) { @@ -1506,9 +1507,9 @@ probe_device_check: (u_int8_t *)malloc((serial_buf->length + 1), M_CAMXPT, M_NOWAIT); if (path->device->serial_num != NULL) { - bcopy(serial_buf->serial_num, - path->device->serial_num, - serial_buf->length); + memcpy(path->device->serial_num, + serial_buf->serial_num, + serial_buf->length); path->device->serial_num_len = serial_buf->length; path->device->serial_num[serial_buf->length] @@ -2433,28 +2434,77 @@ scsi_devise_transport(struct cam_path *path) } static void -scsi_getdev_advinfo(union ccb *start_ccb) +scsi_dev_advinfo(union ccb *start_ccb) { struct cam_ed *device; - struct ccb_getdev_advinfo *cgdai; + struct ccb_dev_advinfo *cdai; off_t amt; device = start_ccb->ccb_h.path->device; - cgdai = &start_ccb->cgdai; - switch(cgdai->buftype) { - case CGDAI_TYPE_SCSI_DEVID: - cgdai->provsiz = device->device_id_len; + cdai = &start_ccb->cdai; + switch(cdai->buftype) { + case CDAI_TYPE_SCSI_DEVID: + if (cdai->flags & CDAI_FLAG_STORE) + break; + cdai->provsiz = device->device_id_len; if (device->device_id_len == 0) break; amt = device->device_id_len; - if (cgdai->provsiz > cgdai->bufsiz) - amt = cgdai->bufsiz; - bcopy(device->device_id, cgdai->buf, amt); + if (cdai->provsiz > cdai->bufsiz) + amt = cdai->bufsiz; + memcpy(cdai->buf, device->device_id, amt); + break; + case CDAI_TYPE_SERIAL_NUM: + if (cdai->flags & CDAI_FLAG_STORE) + break; + cdai->provsiz = device->serial_num_len; + if (device->serial_num_len == 0) + break; + amt = device->serial_num_len; + if (cdai->provsiz > cdai->bufsiz) + amt = cdai->bufsiz; + memcpy(cdai->buf, device->serial_num, amt); + break; + case CDAI_TYPE_PHYS_PATH: + if (cdai->flags & CDAI_FLAG_STORE) { + if (device->physpath != NULL) + free(device->physpath, M_CAMXPT); + device->physpath_len = cdai->bufsiz; + /* Clear existing buffer if zero length */ + if (cdai->bufsiz == 0) + break; + device->physpath = malloc(cdai->bufsiz, M_CAMXPT, M_NOWAIT); + if (device->physpath == NULL) { + start_ccb->ccb_h.status = CAM_REQ_ABORTED; + return; + } + memcpy(device->physpath, cdai->buf, cdai->bufsiz); + } else { + cdai->provsiz = device->physpath_len; + if (device->physpath_len == 0) + break; + amt = device->physpath_len; + if (cdai->provsiz > cdai->bufsiz) + amt = cdai->bufsiz; + memcpy(cdai->buf, device->physpath, amt); + } break; default: break; } start_ccb->ccb_h.status = CAM_REQ_CMP; + + if (cdai->flags & CDAI_FLAG_STORE) { + int owned; + + owned = mtx_owned(start_ccb->ccb_h.path->bus->sim->mtx); + if (owned == 0) + mtx_lock(start_ccb->ccb_h.path->bus->sim->mtx); + xpt_async(AC_ADVINFO_CHANGED, start_ccb->ccb_h.path, + (void *)(uintptr_t)cdai->buftype); + if (owned == 0) + mtx_unlock(start_ccb->ccb_h.path->bus->sim->mtx); + } } static void @@ -2486,9 +2536,9 @@ scsi_action(union ccb *start_ccb) (*(sim->sim_action))(sim, start_ccb); break; } - case XPT_GDEV_ADVINFO: + case XPT_DEV_ADVINFO: { - scsi_getdev_advinfo(start_ccb); + scsi_dev_advinfo(start_ccb); break; } default: diff --git a/sys/dev/ata/chipsets/ata-intel.c b/sys/dev/ata/chipsets/ata-intel.c index 3b514db9ad2..e128051b502 100644 --- a/sys/dev/ata/chipsets/ata-intel.c +++ b/sys/dev/ata/chipsets/ata-intel.c @@ -288,7 +288,9 @@ ata_intel_chipinit(device_t dev) ATA_OUTL(ctlr->r_res2, 0x0C, ATA_INL(ctlr->r_res2, 0x0C) | 0xf); } - } else { + /* Skip BAR(5) on ICH8M Apples, system locks up on access. */ + } else if (ctlr->chip->chipid != ATA_I82801HBM_S1 || + pci_get_subvendor(dev) != 0x106b) { ctlr->r_type2 = SYS_RES_IOPORT; ctlr->r_rid2 = PCIR_BAR(5); ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2, diff --git a/sys/dev/puc/puc.c b/sys/dev/puc/puc.c index b6fa3c5e560..9bb3ceb1649 100644 --- a/sys/dev/puc/puc.c +++ b/sys/dev/puc/puc.c @@ -726,3 +726,41 @@ puc_bus_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) } return (0); } + +int +puc_bus_print_child(device_t dev, device_t child) +{ + struct puc_port *port; + int retval; + + port = device_get_ivars(child); + retval = 0; + + retval += bus_print_child_header(dev, child); + retval += printf(" at port %d", port->p_nr); + retval += bus_print_child_footer(dev, child); + + return (retval); +} + +int +puc_bus_child_location_str(device_t dev, device_t child, char *buf, + size_t buflen) +{ + struct puc_port *port; + + port = device_get_ivars(child); + snprintf(buf, buflen, "port=%d", port->p_nr); + return (0); +} + +int +puc_bus_child_pnpinfo_str(device_t dev, device_t child, char *buf, + size_t buflen) +{ + struct puc_port *port; + + port = device_get_ivars(child); + snprintf(buf, buflen, "type=%d", port->p_type); + return (0); +} diff --git a/sys/dev/puc/puc_bfe.h b/sys/dev/puc/puc_bfe.h index f6d69c407a9..c67fab5f670 100644 --- a/sys/dev/puc/puc_bfe.h +++ b/sys/dev/puc/puc_bfe.h @@ -82,9 +82,12 @@ int puc_bfe_attach(device_t); int puc_bfe_detach(device_t); int puc_bfe_probe(device_t, const struct puc_cfg *); +int puc_bus_child_location_str(device_t, device_t, char *, size_t); +int puc_bus_child_pnpinfo_str(device_t, device_t, char *, size_t); struct resource *puc_bus_alloc_resource(device_t, device_t, int, int *, u_long, u_long, u_long, u_int); int puc_bus_get_resource(device_t, device_t, int, int, u_long *, u_long *); +int puc_bus_print_child(device_t, device_t); int puc_bus_read_ivar(device_t, device_t, int, uintptr_t *); int puc_bus_release_resource(device_t, device_t, int, int, struct resource *); int puc_bus_setup_intr(device_t, device_t, struct resource *, int, diff --git a/sys/dev/puc/puc_pccard.c b/sys/dev/puc/puc_pccard.c index 2cb9513a875..63d57876fca 100644 --- a/sys/dev/puc/puc_pccard.c +++ b/sys/dev/puc/puc_pccard.c @@ -82,7 +82,9 @@ static device_method_t puc_pccard_methods[] = { DEVMETHOD(bus_read_ivar, puc_bus_read_ivar), DEVMETHOD(bus_setup_intr, puc_bus_setup_intr), DEVMETHOD(bus_teardown_intr, puc_bus_teardown_intr), - DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_print_child, puc_bus_print_child), + DEVMETHOD(bus_child_pnpinfo_str, puc_bus_child_pnpinfo_str), + DEVMETHOD(bus_child_location_str, puc_bus_child_location_str), DEVMETHOD(bus_driver_added, bus_generic_driver_added), { 0, 0 } }; diff --git a/sys/dev/puc/puc_pci.c b/sys/dev/puc/puc_pci.c index 9a05b66cc52..8c14717d9bd 100644 --- a/sys/dev/puc/puc_pci.c +++ b/sys/dev/puc/puc_pci.c @@ -132,7 +132,9 @@ static device_method_t puc_pci_methods[] = { DEVMETHOD(bus_read_ivar, puc_bus_read_ivar), DEVMETHOD(bus_setup_intr, puc_bus_setup_intr), DEVMETHOD(bus_teardown_intr, puc_bus_teardown_intr), - DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_print_child, puc_bus_print_child), + DEVMETHOD(bus_child_pnpinfo_str, puc_bus_child_pnpinfo_str), + DEVMETHOD(bus_child_location_str, puc_bus_child_location_str), DEVMETHOD(bus_driver_added, bus_generic_driver_added), { 0, 0 } }; diff --git a/sys/dev/sound/pci/hda/hdac.c b/sys/dev/sound/pci/hda/hdac.c index 5bec624431e..383277cc4d0 100644 --- a/sys/dev/sound/pci/hda/hdac.c +++ b/sys/dev/sound/pci/hda/hdac.c @@ -754,7 +754,17 @@ static const struct { #define HDA_CODEC_CX20561 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5051) #define HDA_CODEC_CX20582 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5066) #define HDA_CODEC_CX20583 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5067) +#define HDA_CODEC_CX20584 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5068) #define HDA_CODEC_CX20585 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5069) +#define HDA_CODEC_CX20590 HDA_CODEC_CONSTRUCT(CONEXANT, 0x506e) +#define HDA_CODEC_CX20631 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5097) +#define HDA_CODEC_CX20632 HDA_CODEC_CONSTRUCT(CONEXANT, 0x5098) +#define HDA_CODEC_CX20641 HDA_CODEC_CONSTRUCT(CONEXANT, 0x50a1) +#define HDA_CODEC_CX20642 HDA_CODEC_CONSTRUCT(CONEXANT, 0x50a2) +#define HDA_CODEC_CX20651 HDA_CODEC_CONSTRUCT(CONEXANT, 0x50ab) +#define HDA_CODEC_CX20652 HDA_CODEC_CONSTRUCT(CONEXANT, 0x50ac) +#define HDA_CODEC_CX20664 HDA_CODEC_CONSTRUCT(CONEXANT, 0x50b8) +#define HDA_CODEC_CX20665 HDA_CODEC_CONSTRUCT(CONEXANT, 0x50b9) #define HDA_CODEC_CXXXXX HDA_CODEC_CONSTRUCT(CONEXANT, 0xffff) /* VIA */ @@ -939,7 +949,17 @@ static const struct { { HDA_CODEC_CX20561, "Conexant CX20561 (Hermosa)" }, { HDA_CODEC_CX20582, "Conexant CX20582 (Pebble)" }, { HDA_CODEC_CX20583, "Conexant CX20583 (Pebble HSF)" }, + { HDA_CODEC_CX20584, "Conexant CX20584" }, { HDA_CODEC_CX20585, "Conexant CX20585" }, + { HDA_CODEC_CX20590, "Conexant CX20590" }, + { HDA_CODEC_CX20631, "Conexant CX20631" }, + { HDA_CODEC_CX20632, "Conexant CX20632" }, + { HDA_CODEC_CX20641, "Conexant CX20641" }, + { HDA_CODEC_CX20642, "Conexant CX20642" }, + { HDA_CODEC_CX20651, "Conexant CX20651" }, + { HDA_CODEC_CX20652, "Conexant CX20652" }, + { HDA_CODEC_CX20664, "Conexant CX20664" }, + { HDA_CODEC_CX20665, "Conexant CX20665" }, { HDA_CODEC_VT1708_8, "VIA VT1708_8" }, { HDA_CODEC_VT1708_9, "VIA VT1708_9" }, { HDA_CODEC_VT1708_A, "VIA VT1708_A" }, @@ -4921,6 +4941,25 @@ hdac_vendor_patch_parse(struct hdac_devinfo *devinfo) if (w != NULL) w->connsenable[0] = 0; break; + case HDA_CODEC_CX20582: + case HDA_CODEC_CX20583: + case HDA_CODEC_CX20584: + case HDA_CODEC_CX20585: + case HDA_CODEC_CX20590: + /* + * These codecs have extra connectivity on record side + * too reach for the present parser. + */ + w = hdac_widget_get(devinfo, 20); + if (w != NULL) + w->connsenable[1] = 0; + w = hdac_widget_get(devinfo, 21); + if (w != NULL) + w->connsenable[1] = 0; + w = hdac_widget_get(devinfo, 22); + if (w != NULL) + w->connsenable[0] = 0; + break; } } diff --git a/sys/dev/xen/blkback/blkback.c b/sys/dev/xen/blkback/blkback.c index 8b412cf7926..e52c34234b9 100644 --- a/sys/dev/xen/blkback/blkback.c +++ b/sys/dev/xen/blkback/blkback.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2009-2010 Spectra Logic Corporation + * Copyright (c) 2009-2011 Spectra Logic Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -61,6 +61,8 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include @@ -153,9 +155,19 @@ MALLOC_DEFINE(M_XENBLOCKBACK, "xbbd", "Xen Block Back Driver Data"); #define XBB_MAX_RING_PAGES \ BLKIF_RING_PAGES(BLKIF_SEGS_TO_BLOCKS(XBB_MAX_SEGMENTS_PER_REQUEST) \ * XBB_MAX_REQUESTS) +/** + * The maximum number of ring pages that we can allow per request list. + * We limit this to the maximum number of segments per request, because + * that is already a reasonable number of segments to aggregate. This + * number should never be smaller than XBB_MAX_SEGMENTS_PER_REQUEST, + * because that would leave situations where we can't dispatch even one + * large request. + */ +#define XBB_MAX_SEGMENTS_PER_REQLIST XBB_MAX_SEGMENTS_PER_REQUEST /*--------------------------- Forward Declarations ---------------------------*/ struct xbb_softc; +struct xbb_xen_req; static void xbb_attach_failed(struct xbb_softc *xbb, int err, const char *fmt, ...) __attribute__((format(printf, 3, 4))); @@ -163,16 +175,15 @@ static int xbb_shutdown(struct xbb_softc *xbb); static int xbb_detach(device_t dev); /*------------------------------ Data Structures -----------------------------*/ -/** - * \brief Object tracking an in-flight I/O from a Xen VBD consumer. - */ -struct xbb_xen_req { - /** - * Linked list links used to aggregate idle request in the - * request free pool (xbb->request_free_slist). - */ - SLIST_ENTRY(xbb_xen_req) links; +STAILQ_HEAD(xbb_xen_req_list, xbb_xen_req); + +typedef enum { + XBB_REQLIST_NONE = 0x00, + XBB_REQLIST_MAPPED = 0x01 +} xbb_reqlist_flags; + +struct xbb_xen_reqlist { /** * Back reference to the parent block back instance for this * request. Used during bio_done handling. @@ -180,17 +191,71 @@ struct xbb_xen_req { struct xbb_softc *xbb; /** - * The remote domain's identifier for this I/O request. + * BLKIF_OP code for this request. */ - uint64_t id; + int operation; + + /** + * Set to BLKIF_RSP_* to indicate request status. + * + * This field allows an error status to be recorded even if the + * delivery of this status must be deferred. Deferred reporting + * is necessary, for example, when an error is detected during + * completion processing of one bio when other bios for this + * request are still outstanding. + */ + int status; + + /** + * Number of 512 byte sectors not transferred. + */ + int residual_512b_sectors; + + /** + * Starting sector number of the first request in the list. + */ + off_t starting_sector_number; + + /** + * If we're going to coalesce, the next contiguous sector would be + * this one. + */ + off_t next_contig_sector; + + /** + * Number of child requests in the list. + */ + int num_children; + + /** + * Number of I/O requests dispatched to the backend. + */ + int pendcnt; + + /** + * Total number of segments for requests in the list. + */ + int nr_segments; + + /** + * Flags for this particular request list. + */ + xbb_reqlist_flags flags; /** * Kernel virtual address space reserved for this request - * structure and used to map the remote domain's pages for + * list structure and used to map the remote domain's pages for * this I/O, into our domain's address space. */ uint8_t *kva; + /** + * Base, psuedo-physical address, corresponding to the start + * of this request's kva region. + */ + uint64_t gnt_base; + + #ifdef XBB_USE_BOUNCE_BUFFERS /** * Pre-allocated domain local memory used to proxy remote @@ -200,43 +265,9 @@ struct xbb_xen_req { #endif /** - * Base, psuedo-physical address, corresponding to the start - * of this request's kva region. + * Array of grant handles (one per page) used to map this request. */ - uint64_t gnt_base; - - /** - * The number of pages currently mapped for this request. - */ - int nr_pages; - - /** - * The number of 512 byte sectors comprising this requests. - */ - int nr_512b_sectors; - - /** - * The number of struct bio requests still outstanding for this - * request on the backend device. This field is only used for - * device (rather than file) backed I/O. - */ - int pendcnt; - - /** - * BLKIF_OP code for this request. - */ - int operation; - - /** - * BLKIF_RSP status code for this request. - * - * This field allows an error status to be recorded even if the - * delivery of this status must be deferred. Deferred reporting - * is necessary, for example, when an error is detected during - * completion processing of one bio when other bios for this - * request are still outstanding. - */ - int status; + grant_handle_t *gnt_handles; /** * Device statistics request ordering type (ordered or simple). @@ -254,9 +285,81 @@ struct xbb_xen_req { struct bintime ds_t0; /** - * Array of grant handles (one per page) used to map this request. + * Linked list of contiguous requests with the same operation type. */ - grant_handle_t *gnt_handles; + struct xbb_xen_req_list contig_req_list; + + /** + * Linked list links used to aggregate idle requests in the + * request list free pool (xbb->reqlist_free_stailq) and pending + * requests waiting for execution (xbb->reqlist_pending_stailq). + */ + STAILQ_ENTRY(xbb_xen_reqlist) links; +}; + +STAILQ_HEAD(xbb_xen_reqlist_list, xbb_xen_reqlist); + +/** + * \brief Object tracking an in-flight I/O from a Xen VBD consumer. + */ +struct xbb_xen_req { + /** + * Linked list links used to aggregate requests into a reqlist + * and to store them in the request free pool. + */ + STAILQ_ENTRY(xbb_xen_req) links; + + /** + * The remote domain's identifier for this I/O request. + */ + uint64_t id; + + /** + * The number of pages currently mapped for this request. + */ + int nr_pages; + + /** + * The number of 512 byte sectors comprising this requests. + */ + int nr_512b_sectors; + + /** + * The number of struct bio requests still outstanding for this + * request on the backend device. This field is only used for + * device (rather than file) backed I/O. + */ + int pendcnt; + + /** + * BLKIF_OP code for this request. + */ + int operation; + + /** + * Storage used for non-native ring requests. + */ + blkif_request_t ring_req_storage; + + /** + * Pointer to the Xen request in the ring. + */ + blkif_request_t *ring_req; + + /** + * Consumer index for this request. + */ + RING_IDX req_ring_idx; + + /** + * The start time for this request. + */ + struct bintime ds_t0; + + /** + * Pointer back to our parent request list. + */ + struct xbb_xen_reqlist *reqlist; }; SLIST_HEAD(xbb_xen_req_slist, xbb_xen_req); @@ -321,7 +424,10 @@ typedef enum XBBF_RESOURCE_SHORTAGE = 0x04, /** Connection teardown in progress. */ - XBBF_SHUTDOWN = 0x08 + XBBF_SHUTDOWN = 0x08, + + /** A thread is already performing shutdown processing. */ + XBBF_IN_SHUTDOWN = 0x10 } xbb_flag_t; /** Backend device type. */ @@ -399,7 +505,7 @@ struct xbb_file_data { * Only a single file based request is outstanding per-xbb instance, * so we only need one of these. */ - struct iovec xiovecs[XBB_MAX_SEGMENTS_PER_REQUEST]; + struct iovec xiovecs[XBB_MAX_SEGMENTS_PER_REQLIST]; #ifdef XBB_USE_BOUNCE_BUFFERS /** @@ -411,7 +517,7 @@ struct xbb_file_data { * bounce-out the read data. This array serves as the temporary * storage for this saved data. */ - struct iovec saved_xiovecs[XBB_MAX_SEGMENTS_PER_REQUEST]; + struct iovec saved_xiovecs[XBB_MAX_SEGMENTS_PER_REQLIST]; /** * \brief Array of memoized bounce buffer kva offsets used @@ -422,7 +528,7 @@ struct xbb_file_data { * the request sg elements is unavoidable. We memoize the computed * bounce address here to reduce the cost of the second walk. */ - void *xiovecs_vaddr[XBB_MAX_SEGMENTS_PER_REQUEST]; + void *xiovecs_vaddr[XBB_MAX_SEGMENTS_PER_REQLIST]; #endif /* XBB_USE_BOUNCE_BUFFERS */ }; @@ -437,9 +543,9 @@ union xbb_backend_data { /** * Function signature of backend specific I/O handlers. */ -typedef int (*xbb_dispatch_t)(struct xbb_softc *xbb, blkif_request_t *ring_req, - struct xbb_xen_req *req, int nseg, - int operation, int flags); +typedef int (*xbb_dispatch_t)(struct xbb_softc *xbb, + struct xbb_xen_reqlist *reqlist, int operation, + int flags); /** * Per-instance configuration data. @@ -467,14 +573,23 @@ struct xbb_softc { xbb_dispatch_t dispatch_io; /** The number of requests outstanding on the backend device/file. */ - u_int active_request_count; + int active_request_count; /** Free pool of request tracking structures. */ - struct xbb_xen_req_slist request_free_slist; + struct xbb_xen_req_list request_free_stailq; /** Array, sized at connection time, of request tracking structures. */ struct xbb_xen_req *requests; + /** Free pool of request list structures. */ + struct xbb_xen_reqlist_list reqlist_free_stailq; + + /** List of pending request lists awaiting execution. */ + struct xbb_xen_reqlist_list reqlist_pending_stailq; + + /** Array, sized at connection time, of request list structures. */ + struct xbb_xen_reqlist *request_lists; + /** * Global pool of kva used for mapping remote domain ring * and I/O transaction data. @@ -487,6 +602,15 @@ struct xbb_softc { /** The size of the global kva pool. */ int kva_size; + /** The size of the KVA area used for request lists. */ + int reqlist_kva_size; + + /** The number of pages of KVA used for request lists */ + int reqlist_kva_pages; + + /** Bitmap of free KVA pages */ + bitstr_t *kva_free; + /** * \brief Cached value of the front-end's domain id. * @@ -508,12 +632,12 @@ struct xbb_softc { int abi; /** - * \brief The maximum number of requests allowed to be in - * flight at a time. + * \brief The maximum number of requests and request lists allowed + * to be in flight at a time. * * This value is negotiated via the XenStore. */ - uint32_t max_requests; + u_int max_requests; /** * \brief The maximum number of segments (1 page per segment) @@ -521,7 +645,15 @@ struct xbb_softc { * * This value is negotiated via the XenStore. */ - uint32_t max_request_segments; + u_int max_request_segments; + + /** + * \brief Maximum number of segments per request list. + * + * This value is derived from and will generally be larger than + * max_request_segments. + */ + u_int max_reqlist_segments; /** * The maximum size of any request to this back-end @@ -529,7 +661,13 @@ struct xbb_softc { * * This value is negotiated via the XenStore. */ - uint32_t max_request_size; + u_int max_request_size; + + /** + * The maximum size of any request list. This is derived directly + * from max_reqlist_segments. + */ + u_int max_reqlist_size; /** Various configuration and state bit flags. */ xbb_flag_t flags; @@ -574,6 +712,7 @@ struct xbb_softc { struct vnode *vn; union xbb_backend_data backend; + /** The native sector size of the backend. */ u_int sector_size; @@ -598,7 +737,14 @@ struct xbb_softc { * * Ring processing is serialized so we only need one of these. */ - struct xbb_sg xbb_sgs[XBB_MAX_SEGMENTS_PER_REQUEST]; + struct xbb_sg xbb_sgs[XBB_MAX_SEGMENTS_PER_REQLIST]; + + /** + * Temporary grant table map used in xbb_dispatch_io(). When + * XBB_MAX_SEGMENTS_PER_REQLIST gets large, keeping this on the + * stack could cause a stack overflow. + */ + struct gnttab_map_grant_ref maps[XBB_MAX_SEGMENTS_PER_REQLIST]; /** Mutex protecting per-instance data. */ struct mtx lock; @@ -614,8 +760,51 @@ struct xbb_softc { int pseudo_phys_res_id; #endif - /** I/O statistics. */ + /** + * I/O statistics from BlockBack dispatch down. These are + * coalesced requests, and we start them right before execution. + */ struct devstat *xbb_stats; + + /** + * I/O statistics coming into BlockBack. These are the requests as + * we get them from BlockFront. They are started as soon as we + * receive a request, and completed when the I/O is complete. + */ + struct devstat *xbb_stats_in; + + /** Disable sending flush to the backend */ + int disable_flush; + + /** Send a real flush for every N flush requests */ + int flush_interval; + + /** Count of flush requests in the interval */ + int flush_count; + + /** Don't coalesce requests if this is set */ + int no_coalesce_reqs; + + /** Number of requests we have received */ + uint64_t reqs_received; + + /** Number of requests we have completed*/ + uint64_t reqs_completed; + + /** How many forced dispatches (i.e. without coalescing) have happend */ + uint64_t forced_dispatch; + + /** How many normal dispatches have happend */ + uint64_t normal_dispatch; + + /** How many total dispatches have happend */ + uint64_t total_dispatch; + + /** How many times we have run out of KVA */ + uint64_t kva_shortages; + + /** How many times we have run out of request structures */ + uint64_t request_shortages; }; /*---------------------------- Request Processing ----------------------------*/ @@ -633,21 +822,14 @@ xbb_get_req(struct xbb_softc *xbb) struct xbb_xen_req *req; req = NULL; - mtx_lock(&xbb->lock); - /* - * Do not allow new requests to be allocated while we - * are shutting down. - */ - if ((xbb->flags & XBBF_SHUTDOWN) == 0) { - if ((req = SLIST_FIRST(&xbb->request_free_slist)) != NULL) { - SLIST_REMOVE_HEAD(&xbb->request_free_slist, links); - xbb->active_request_count++; - } else { - xbb->flags |= XBBF_RESOURCE_SHORTAGE; - } + mtx_assert(&xbb->lock, MA_OWNED); + + if ((req = STAILQ_FIRST(&xbb->request_free_stailq)) != NULL) { + STAILQ_REMOVE_HEAD(&xbb->request_free_stailq, links); + xbb->active_request_count++; } - mtx_unlock(&xbb->lock); + return (req); } @@ -660,34 +842,40 @@ xbb_get_req(struct xbb_softc *xbb) static inline void xbb_release_req(struct xbb_softc *xbb, struct xbb_xen_req *req) { - int wake_thread; + mtx_assert(&xbb->lock, MA_OWNED); - mtx_lock(&xbb->lock); - wake_thread = xbb->flags & XBBF_RESOURCE_SHORTAGE; - xbb->flags &= ~XBBF_RESOURCE_SHORTAGE; - SLIST_INSERT_HEAD(&xbb->request_free_slist, req, links); + STAILQ_INSERT_HEAD(&xbb->request_free_stailq, req, links); xbb->active_request_count--; - if ((xbb->flags & XBBF_SHUTDOWN) != 0) { - /* - * Shutdown is in progress. See if we can - * progress further now that one more request - * has completed and been returned to the - * free pool. - */ - xbb_shutdown(xbb); - } - mtx_unlock(&xbb->lock); + KASSERT(xbb->active_request_count >= 0, + ("xbb_release_req: negative active count")); +} - if (wake_thread != 0) - taskqueue_enqueue(xbb->io_taskqueue, &xbb->io_task); +/** + * Return an xbb_xen_req_list of allocated xbb_xen_reqs to the free pool. + * + * \param xbb Per-instance xbb configuration structure. + * \param req_list The list of requests to free. + * \param nreqs The number of items in the list. + */ +static inline void +xbb_release_reqs(struct xbb_softc *xbb, struct xbb_xen_req_list *req_list, + int nreqs) +{ + mtx_assert(&xbb->lock, MA_OWNED); + + STAILQ_CONCAT(&xbb->request_free_stailq, req_list); + xbb->active_request_count -= nreqs; + + KASSERT(xbb->active_request_count >= 0, + ("xbb_release_reqs: negative active count")); } /** * Given a page index and 512b sector offset within that page, * calculate an offset into a request's kva region. * - * \param req The request structure whose kva region will be accessed. + * \param reqlist The request structure whose kva region will be accessed. * \param pagenr The page index used to compute the kva offset. * \param sector The 512b sector index used to compute the page relative * kva offset. @@ -695,9 +883,9 @@ xbb_release_req(struct xbb_softc *xbb, struct xbb_xen_req *req) * \return The computed global KVA offset. */ static inline uint8_t * -xbb_req_vaddr(struct xbb_xen_req *req, int pagenr, int sector) +xbb_reqlist_vaddr(struct xbb_xen_reqlist *reqlist, int pagenr, int sector) { - return (req->kva + (PAGE_SIZE * pagenr) + (sector << 9)); + return (reqlist->kva + (PAGE_SIZE * pagenr) + (sector << 9)); } #ifdef XBB_USE_BOUNCE_BUFFERS @@ -705,7 +893,7 @@ xbb_req_vaddr(struct xbb_xen_req *req, int pagenr, int sector) * Given a page index and 512b sector offset within that page, * calculate an offset into a request's local bounce memory region. * - * \param req The request structure whose bounce region will be accessed. + * \param reqlist The request structure whose bounce region will be accessed. * \param pagenr The page index used to compute the bounce offset. * \param sector The 512b sector index used to compute the page relative * bounce offset. @@ -713,9 +901,9 @@ xbb_req_vaddr(struct xbb_xen_req *req, int pagenr, int sector) * \return The computed global bounce buffer address. */ static inline uint8_t * -xbb_req_bounce_addr(struct xbb_xen_req *req, int pagenr, int sector) +xbb_reqlist_bounce_addr(struct xbb_xen_reqlist *reqlist, int pagenr, int sector) { - return (req->bounce + (PAGE_SIZE * pagenr) + (sector << 9)); + return (reqlist->bounce + (PAGE_SIZE * pagenr) + (sector << 9)); } #endif @@ -724,7 +912,7 @@ xbb_req_bounce_addr(struct xbb_xen_req *req, int pagenr, int sector) * calculate an offset into the request's memory region that the * underlying backend device/file should use for I/O. * - * \param req The request structure whose I/O region will be accessed. + * \param reqlist The request structure whose I/O region will be accessed. * \param pagenr The page index used to compute the I/O offset. * \param sector The 512b sector index used to compute the page relative * I/O offset. @@ -736,12 +924,12 @@ xbb_req_bounce_addr(struct xbb_xen_req *req, int pagenr, int sector) * this request. */ static inline uint8_t * -xbb_req_ioaddr(struct xbb_xen_req *req, int pagenr, int sector) +xbb_reqlist_ioaddr(struct xbb_xen_reqlist *reqlist, int pagenr, int sector) { #ifdef XBB_USE_BOUNCE_BUFFERS - return (xbb_req_bounce_addr(req, pagenr, sector)); + return (xbb_reqlist_bounce_addr(reqlist, pagenr, sector)); #else - return (xbb_req_vaddr(req, pagenr, sector)); + return (xbb_reqlist_vaddr(reqlist, pagenr, sector)); #endif } @@ -750,7 +938,7 @@ xbb_req_ioaddr(struct xbb_xen_req *req, int pagenr, int sector) * an offset into the local psuedo-physical address space used to map a * front-end's request data into a request. * - * \param req The request structure whose pseudo-physical region + * \param reqlist The request list structure whose pseudo-physical region * will be accessed. * \param pagenr The page index used to compute the pseudo-physical offset. * \param sector The 512b sector index used to compute the page relative @@ -763,10 +951,126 @@ xbb_req_ioaddr(struct xbb_xen_req *req, int pagenr, int sector) * this request. */ static inline uintptr_t -xbb_req_gntaddr(struct xbb_xen_req *req, int pagenr, int sector) +xbb_get_gntaddr(struct xbb_xen_reqlist *reqlist, int pagenr, int sector) { - return ((uintptr_t)(req->gnt_base - + (PAGE_SIZE * pagenr) + (sector << 9))); + struct xbb_softc *xbb; + + xbb = reqlist->xbb; + + return ((uintptr_t)(xbb->gnt_base_addr + + (uintptr_t)(reqlist->kva - xbb->kva) + + (PAGE_SIZE * pagenr) + (sector << 9))); +} + +/** + * Get Kernel Virtual Address space for mapping requests. + * + * \param xbb Per-instance xbb configuration structure. + * \param nr_pages Number of pages needed. + * \param check_only If set, check for free KVA but don't allocate it. + * \param have_lock If set, xbb lock is already held. + * + * \return On success, a pointer to the allocated KVA region. Otherwise NULL. + * + * Note: This should be unnecessary once we have either chaining or + * scatter/gather support for struct bio. At that point we'll be able to + * put multiple addresses and lengths in one bio/bio chain and won't need + * to map everything into one virtual segment. + */ +static uint8_t * +xbb_get_kva(struct xbb_softc *xbb, int nr_pages) +{ + intptr_t first_clear, num_clear; + uint8_t *free_kva; + int i; + + KASSERT(nr_pages != 0, ("xbb_get_kva of zero length")); + + first_clear = 0; + free_kva = NULL; + + mtx_lock(&xbb->lock); + + /* + * Look for the first available page. If there are none, we're done. + */ + bit_ffc(xbb->kva_free, xbb->reqlist_kva_pages, &first_clear); + + if (first_clear == -1) + goto bailout; + + /* + * Starting at the first available page, look for consecutive free + * pages that will satisfy the user's request. + */ + for (i = first_clear, num_clear = 0; i < xbb->reqlist_kva_pages; i++) { + /* + * If this is true, the page is used, so we have to reset + * the number of clear pages and the first clear page + * (since it pointed to a region with an insufficient number + * of clear pages). + */ + if (bit_test(xbb->kva_free, i)) { + num_clear = 0; + first_clear = -1; + continue; + } + + if (first_clear == -1) + first_clear = i; + + /* + * If this is true, we've found a large enough free region + * to satisfy the request. + */ + if (++num_clear == nr_pages) { + + bit_nset(xbb->kva_free, first_clear, + first_clear + nr_pages - 1); + + free_kva = xbb->kva + + (uint8_t *)(first_clear * PAGE_SIZE); + + KASSERT(free_kva >= (uint8_t *)xbb->kva && + free_kva + (nr_pages * PAGE_SIZE) <= + (uint8_t *)xbb->ring_config.va, + ("Free KVA %p len %d out of range, " + "kva = %#jx, ring VA = %#jx\n", free_kva, + nr_pages * PAGE_SIZE, (uintmax_t)xbb->kva, + (uintmax_t)xbb->ring_config.va)); + break; + } + } + +bailout: + + if (free_kva == NULL) { + xbb->flags |= XBBF_RESOURCE_SHORTAGE; + xbb->kva_shortages++; + } + + mtx_unlock(&xbb->lock); + + return (free_kva); +} + +/** + * Free allocated KVA. + * + * \param xbb Per-instance xbb configuration structure. + * \param kva_ptr Pointer to allocated KVA region. + * \param nr_pages Number of pages in the KVA region. + */ +static void +xbb_free_kva(struct xbb_softc *xbb, uint8_t *kva_ptr, int nr_pages) +{ + intptr_t start_page; + + mtx_assert(&xbb->lock, MA_OWNED); + + start_page = (intptr_t)(kva_ptr - xbb->kva) >> PAGE_SHIFT; + bit_nclear(xbb->kva_free, start_page, start_page + nr_pages - 1); + } /** @@ -775,23 +1079,23 @@ xbb_req_gntaddr(struct xbb_xen_req *req, int pagenr, int sector) * \param req The request structure to unmap. */ static void -xbb_unmap_req(struct xbb_xen_req *req) +xbb_unmap_reqlist(struct xbb_xen_reqlist *reqlist) { - struct gnttab_unmap_grant_ref unmap[XBB_MAX_SEGMENTS_PER_REQUEST]; + struct gnttab_unmap_grant_ref unmap[XBB_MAX_SEGMENTS_PER_REQLIST]; u_int i; u_int invcount; int error; invcount = 0; - for (i = 0; i < req->nr_pages; i++) { + for (i = 0; i < reqlist->nr_segments; i++) { - if (req->gnt_handles[i] == GRANT_REF_INVALID) + if (reqlist->gnt_handles[i] == GRANT_REF_INVALID) continue; - unmap[invcount].host_addr = xbb_req_gntaddr(req, i, 0); + unmap[invcount].host_addr = xbb_get_gntaddr(reqlist, i, 0); unmap[invcount].dev_bus_addr = 0; - unmap[invcount].handle = req->gnt_handles[i]; - req->gnt_handles[i] = GRANT_REF_INVALID; + unmap[invcount].handle = reqlist->gnt_handles[i]; + reqlist->gnt_handles[i] = GRANT_REF_INVALID; invcount++; } @@ -800,6 +1104,175 @@ xbb_unmap_req(struct xbb_xen_req *req) KASSERT(error == 0, ("Grant table operation failed")); } +/** + * Allocate an internal transaction tracking structure from the free pool. + * + * \param xbb Per-instance xbb configuration structure. + * + * \return On success, a pointer to the allocated xbb_xen_reqlist structure. + * Otherwise NULL. + */ +static inline struct xbb_xen_reqlist * +xbb_get_reqlist(struct xbb_softc *xbb) +{ + struct xbb_xen_reqlist *reqlist; + + reqlist = NULL; + + mtx_assert(&xbb->lock, MA_OWNED); + + if ((reqlist = STAILQ_FIRST(&xbb->reqlist_free_stailq)) != NULL) { + + STAILQ_REMOVE_HEAD(&xbb->reqlist_free_stailq, links); + reqlist->flags = XBB_REQLIST_NONE; + reqlist->kva = NULL; + reqlist->status = BLKIF_RSP_OKAY; + reqlist->residual_512b_sectors = 0; + reqlist->num_children = 0; + reqlist->nr_segments = 0; + STAILQ_INIT(&reqlist->contig_req_list); + } + + return (reqlist); +} + +/** + * Return an allocated transaction tracking structure to the free pool. + * + * \param xbb Per-instance xbb configuration structure. + * \param req The request list structure to free. + * \param wakeup If set, wakeup the work thread if freeing this reqlist + * during a resource shortage condition. + */ +static inline void +xbb_release_reqlist(struct xbb_softc *xbb, struct xbb_xen_reqlist *reqlist, + int wakeup) +{ + + mtx_lock(&xbb->lock); + + if (wakeup) { + wakeup = xbb->flags & XBBF_RESOURCE_SHORTAGE; + xbb->flags &= ~XBBF_RESOURCE_SHORTAGE; + } + + if (reqlist->kva != NULL) + xbb_free_kva(xbb, reqlist->kva, reqlist->nr_segments); + + xbb_release_reqs(xbb, &reqlist->contig_req_list, reqlist->num_children); + + STAILQ_INSERT_TAIL(&xbb->reqlist_free_stailq, reqlist, links); + + if ((xbb->flags & XBBF_SHUTDOWN) != 0) { + /* + * Shutdown is in progress. See if we can + * progress further now that one more request + * has completed and been returned to the + * free pool. + */ + xbb_shutdown(xbb); + } + + mtx_unlock(&xbb->lock); + + if (wakeup != 0) + taskqueue_enqueue(xbb->io_taskqueue, &xbb->io_task); +} + +/** + * Request resources and do basic request setup. + * + * \param xbb Per-instance xbb configuration structure. + * \param reqlist Pointer to reqlist pointer. + * \param ring_req Pointer to a block ring request. + * \param ring_index The ring index of this request. + * + * \return 0 for success, non-zero for failure. + */ +static int +xbb_get_resources(struct xbb_softc *xbb, struct xbb_xen_reqlist **reqlist, + blkif_request_t *ring_req, RING_IDX ring_idx) +{ + struct xbb_xen_reqlist *nreqlist; + struct xbb_xen_req *nreq; + + nreqlist = NULL; + nreq = NULL; + + mtx_lock(&xbb->lock); + + /* + * We don't allow new resources to be allocated if we're in the + * process of shutting down. + */ + if ((xbb->flags & XBBF_SHUTDOWN) != 0) { + mtx_unlock(&xbb->lock); + return (1); + } + + /* + * Allocate a reqlist if the caller doesn't have one already. + */ + if (*reqlist == NULL) { + nreqlist = xbb_get_reqlist(xbb); + if (nreqlist == NULL) + goto bailout_error; + } + + /* We always allocate a request. */ + nreq = xbb_get_req(xbb); + if (nreq == NULL) + goto bailout_error; + + mtx_unlock(&xbb->lock); + + if (*reqlist == NULL) { + *reqlist = nreqlist; + nreqlist->operation = ring_req->operation; + nreqlist->starting_sector_number = ring_req->sector_number; + STAILQ_INSERT_TAIL(&xbb->reqlist_pending_stailq, nreqlist, + links); + } + + nreq->reqlist = *reqlist; + nreq->req_ring_idx = ring_idx; + + if (xbb->abi != BLKIF_PROTOCOL_NATIVE) { + bcopy(ring_req, &nreq->ring_req_storage, sizeof(*ring_req)); + nreq->ring_req = &nreq->ring_req_storage; + } else { + nreq->ring_req = ring_req; + } + + binuptime(&nreq->ds_t0); + devstat_start_transaction(xbb->xbb_stats_in, &nreq->ds_t0); + STAILQ_INSERT_TAIL(&(*reqlist)->contig_req_list, nreq, links); + (*reqlist)->num_children++; + (*reqlist)->nr_segments += ring_req->nr_segments; + + return (0); + +bailout_error: + + /* + * We're out of resources, so set the shortage flag. The next time + * a request is released, we'll try waking up the work thread to + * see if we can allocate more resources. + */ + xbb->flags |= XBBF_RESOURCE_SHORTAGE; + xbb->request_shortages++; + + if (nreq != NULL) + xbb_release_req(xbb, nreq); + + mtx_unlock(&xbb->lock); + + if (nreqlist != NULL) + xbb_release_reqlist(xbb, nreqlist, /*wakeup*/ 0); + + return (1); +} + /** * Create and transmit a response to a blkif request. * @@ -862,6 +1335,8 @@ xbb_send_response(struct xbb_softc *xbb, struct xbb_xen_req *req, int status) more_to_do = 1; } + xbb->reqs_completed++; + mtx_unlock(&xbb->lock); if (more_to_do) @@ -871,6 +1346,70 @@ xbb_send_response(struct xbb_softc *xbb, struct xbb_xen_req *req, int status) notify_remote_via_irq(xbb->irq); } +/** + * Complete a request list. + * + * \param xbb Per-instance xbb configuration structure. + * \param reqlist Allocated internal request list structure. + */ +static void +xbb_complete_reqlist(struct xbb_softc *xbb, struct xbb_xen_reqlist *reqlist) +{ + struct xbb_xen_req *nreq; + off_t sectors_sent; + + sectors_sent = 0; + + if (reqlist->flags & XBB_REQLIST_MAPPED) + xbb_unmap_reqlist(reqlist); + + /* + * All I/O is done, send the response. A lock should not be + * necessary here because the request list is complete, and + * therefore this is the only context accessing this request + * right now. The functions we call do their own locking if + * necessary. + */ + STAILQ_FOREACH(nreq, &reqlist->contig_req_list, links) { + off_t cur_sectors_sent; + + xbb_send_response(xbb, nreq, reqlist->status); + + /* We don't report bytes sent if there is an error. */ + if (reqlist->status == BLKIF_RSP_OKAY) + cur_sectors_sent = nreq->nr_512b_sectors; + else + cur_sectors_sent = 0; + + sectors_sent += cur_sectors_sent; + + devstat_end_transaction(xbb->xbb_stats_in, + /*bytes*/cur_sectors_sent << 9, + reqlist->ds_tag_type, + reqlist->ds_trans_type, + /*now*/NULL, + /*then*/&nreq->ds_t0); + } + + /* + * Take out any sectors not sent. If we wind up negative (which + * might happen if an error is reported as well as a residual), just + * report 0 sectors sent. + */ + sectors_sent -= reqlist->residual_512b_sectors; + if (sectors_sent < 0) + sectors_sent = 0; + + devstat_end_transaction(xbb->xbb_stats, + /*bytes*/ sectors_sent << 9, + reqlist->ds_tag_type, + reqlist->ds_trans_type, + /*now*/NULL, + /*then*/&reqlist->ds_t0); + + xbb_release_reqlist(xbb, reqlist, /*wakeup*/ 1); +} + /** * Completion handler for buffer I/O requests issued by the device * backend driver. @@ -881,18 +1420,34 @@ xbb_send_response(struct xbb_softc *xbb, struct xbb_xen_req *req, int status) static void xbb_bio_done(struct bio *bio) { - struct xbb_softc *xbb; - struct xbb_xen_req *req; + struct xbb_softc *xbb; + struct xbb_xen_reqlist *reqlist; - req = bio->bio_caller1; - xbb = req->xbb; + reqlist = bio->bio_caller1; + xbb = reqlist->xbb; - /* Only include transferred I/O in stats. */ - req->nr_512b_sectors -= bio->bio_resid >> 9; + reqlist->residual_512b_sectors += bio->bio_resid >> 9; + + /* + * This is a bit imprecise. With aggregated I/O a single + * request list can contain multiple front-end requests and + * a multiple bios may point to a single request. By carefully + * walking the request list, we could map residuals and errors + * back to the original front-end request, but the interface + * isn't sufficiently rich for us to properly report the error. + * So, we just treat the entire request list as having failed if an + * error occurs on any part. And, if an error occurs, we treat + * the amount of data transferred as 0. + * + * For residuals, we report it on the overall aggregated device, + * but not on the individual requests, since we don't currently + * do the work to determine which front-end request to which the + * residual applies. + */ if (bio->bio_error) { DPRINTF("BIO returned error %d for operation on device %s\n", bio->bio_error, xbb->dev_name); - req->status = BLKIF_RSP_ERROR; + reqlist->status = BLKIF_RSP_ERROR; if (bio->bio_error == ENXIO && xenbus_get_state(xbb->dev) == XenbusStateConnected) { @@ -911,23 +1466,18 @@ xbb_bio_done(struct bio *bio) vm_offset_t kva_offset; kva_offset = (vm_offset_t)bio->bio_data - - (vm_offset_t)req->bounce; - memcpy((uint8_t *)req->kva + kva_offset, + - (vm_offset_t)reqlist->bounce; + memcpy((uint8_t *)reqlist->kva + kva_offset, bio->bio_data, bio->bio_bcount); } #endif /* XBB_USE_BOUNCE_BUFFERS */ - if (atomic_fetchadd_int(&req->pendcnt, -1) == 1) { - xbb_unmap_req(req); - xbb_send_response(xbb, req, req->status); - devstat_end_transaction(xbb->xbb_stats, - /*bytes*/req->nr_512b_sectors << 9, - req->ds_tag_type, - req->ds_trans_type, - /*now*/NULL, - /*then*/&req->ds_t0); - xbb_release_req(xbb, req); - } + /* + * Decrement the pending count for the request list. When we're + * done with the requests, send status back for all of them. + */ + if (atomic_fetchadd_int(&reqlist->pendcnt, -1) == 1) + xbb_complete_reqlist(xbb, reqlist); g_destroy_bio(bio); } @@ -936,228 +1486,315 @@ xbb_bio_done(struct bio *bio) * Parse a blkif request into an internal request structure and send * it to the backend for processing. * - * \param xbb Per-instance xbb configuration structure. - * \param ring_req Front-end's I/O request as pulled from the shared - * communication ring. - * \param req Allocated internal request structure. - * \param req_ring_idx The location of ring_req within the shared - * communication ring. + * \param xbb Per-instance xbb configuration structure. + * \param reqlist Allocated internal request list structure. * + * \return On success, 0. For resource shortages, non-zero. + * * This routine performs the backend common aspects of request parsing * including compiling an internal request structure, parsing the S/G * list and any secondary ring requests in which they may reside, and * the mapping of front-end I/O pages into our domain. */ -static void -xbb_dispatch_io(struct xbb_softc *xbb, blkif_request_t *ring_req, - struct xbb_xen_req *req, RING_IDX req_ring_idx) +static int +xbb_dispatch_io(struct xbb_softc *xbb, struct xbb_xen_reqlist *reqlist) { - struct gnttab_map_grant_ref maps[XBB_MAX_SEGMENTS_PER_REQUEST]; struct xbb_sg *xbb_sg; struct gnttab_map_grant_ref *map; struct blkif_request_segment *sg; struct blkif_request_segment *last_block_sg; + struct xbb_xen_req *nreq; u_int nseg; u_int seg_idx; u_int block_segs; int nr_sects; + int total_sects; int operation; uint8_t bio_flags; int error; - nseg = ring_req->nr_segments; - nr_sects = 0; - req->xbb = xbb; - req->id = ring_req->id; - req->operation = ring_req->operation; - req->status = BLKIF_RSP_OKAY; - req->ds_tag_type = DEVSTAT_TAG_SIMPLE; - req->nr_pages = nseg; - req->nr_512b_sectors = 0; + reqlist->ds_tag_type = DEVSTAT_TAG_SIMPLE; bio_flags = 0; - sg = NULL; + total_sects = 0; + nr_sects = 0; - binuptime(&req->ds_t0); - devstat_start_transaction(xbb->xbb_stats, &req->ds_t0); + /* + * First determine whether we have enough free KVA to satisfy this + * request list. If not, tell xbb_run_queue() so it can go to + * sleep until we have more KVA. + */ + reqlist->kva = NULL; + if (reqlist->nr_segments != 0) { + reqlist->kva = xbb_get_kva(xbb, reqlist->nr_segments); + if (reqlist->kva == NULL) { + /* + * If we're out of KVA, return ENOMEM. + */ + return (ENOMEM); + } + } - switch (req->operation) { + binuptime(&reqlist->ds_t0); + devstat_start_transaction(xbb->xbb_stats, &reqlist->ds_t0); + + switch (reqlist->operation) { case BLKIF_OP_WRITE_BARRIER: bio_flags |= BIO_ORDERED; - req->ds_tag_type = DEVSTAT_TAG_ORDERED; + reqlist->ds_tag_type = DEVSTAT_TAG_ORDERED; /* FALLTHROUGH */ case BLKIF_OP_WRITE: operation = BIO_WRITE; - req->ds_trans_type = DEVSTAT_WRITE; + reqlist->ds_trans_type = DEVSTAT_WRITE; if ((xbb->flags & XBBF_READ_ONLY) != 0) { DPRINTF("Attempt to write to read only device %s\n", xbb->dev_name); - goto fail_send_response; + reqlist->status = BLKIF_RSP_ERROR; + goto send_response; } break; case BLKIF_OP_READ: operation = BIO_READ; - req->ds_trans_type = DEVSTAT_READ; + reqlist->ds_trans_type = DEVSTAT_READ; break; case BLKIF_OP_FLUSH_DISKCACHE: + /* + * If this is true, the user has requested that we disable + * flush support. So we just complete the requests + * successfully. + */ + if (xbb->disable_flush != 0) { + goto send_response; + } + + /* + * The user has requested that we only send a real flush + * for every N flush requests. So keep count, and either + * complete the request immediately or queue it for the + * backend. + */ + if (xbb->flush_interval != 0) { + if (++(xbb->flush_count) < xbb->flush_interval) { + goto send_response; + } else + xbb->flush_count = 0; + } + operation = BIO_FLUSH; - req->ds_tag_type = DEVSTAT_TAG_ORDERED; - req->ds_trans_type = DEVSTAT_NO_DATA; + reqlist->ds_tag_type = DEVSTAT_TAG_ORDERED; + reqlist->ds_trans_type = DEVSTAT_NO_DATA; goto do_dispatch; /*NOTREACHED*/ default: DPRINTF("error: unknown block io operation [%d]\n", - req->operation); - goto fail_send_response; + reqlist->operation); + reqlist->status = BLKIF_RSP_ERROR; + goto send_response; } - /* Check that number of segments is sane. */ - if (unlikely(nseg == 0) - || unlikely(nseg > xbb->max_request_segments)) { - DPRINTF("Bad number of segments in request (%d)\n", nseg); - goto fail_send_response; - } - - map = maps; + reqlist->xbb = xbb; xbb_sg = xbb->xbb_sgs; - block_segs = MIN(req->nr_pages, BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK); - sg = ring_req->seg; - last_block_sg = sg + block_segs; + map = xbb->maps; seg_idx = 0; - while (1) { - while (sg < last_block_sg) { - - xbb_sg->first_sect = sg->first_sect; - xbb_sg->last_sect = sg->last_sect; - xbb_sg->nsect = - (int8_t)(sg->last_sect - sg->first_sect + 1); + STAILQ_FOREACH(nreq, &reqlist->contig_req_list, links) { + blkif_request_t *ring_req; + RING_IDX req_ring_idx; + u_int req_seg_idx; - if ((sg->last_sect >= (PAGE_SIZE >> 9)) - || (xbb_sg->nsect <= 0)) - goto fail_send_response; + ring_req = nreq->ring_req; + req_ring_idx = nreq->req_ring_idx; + nr_sects = 0; + nseg = ring_req->nr_segments; + nreq->id = ring_req->id; + nreq->nr_pages = nseg; + nreq->nr_512b_sectors = 0; + req_seg_idx = 0; + sg = NULL; - nr_sects += xbb_sg->nsect; - map->host_addr = xbb_req_gntaddr(req, seg_idx, - /*sector*/0); - map->flags = GNTMAP_host_map; - map->ref = sg->gref; - map->dom = xbb->otherend_id; - if (operation == BIO_WRITE) - map->flags |= GNTMAP_readonly; - sg++; - map++; - xbb_sg++; - seg_idx++; + /* Check that number of segments is sane. */ + if (unlikely(nseg == 0) + || unlikely(nseg > xbb->max_request_segments)) { + DPRINTF("Bad number of segments in request (%d)\n", + nseg); + reqlist->status = BLKIF_RSP_ERROR; + goto send_response; } - block_segs = MIN(nseg - seg_idx, - BLKIF_MAX_SEGMENTS_PER_SEGMENT_BLOCK); - if (block_segs == 0) - break; - - /* - * Fetch the next request block full of SG elements. - * For now, only the spacing between entries is different - * in the different ABIs, not the sg entry layout. - */ - req_ring_idx++; - switch (xbb->abi) { - case BLKIF_PROTOCOL_NATIVE: - sg = BLKRING_GET_SG_REQUEST(&xbb->rings.native, - req_ring_idx); - break; - case BLKIF_PROTOCOL_X86_32: - { - sg = BLKRING_GET_SG_REQUEST(&xbb->rings.x86_32, - req_ring_idx); - break; - } - case BLKIF_PROTOCOL_X86_64: - { - sg = BLKRING_GET_SG_REQUEST(&xbb->rings.x86_64, - req_ring_idx); - break; - } - default: - panic("Unexpected blkif protocol ABI."); - /* NOTREACHED */ - } + block_segs = MIN(nreq->nr_pages, + BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK); + sg = ring_req->seg; last_block_sg = sg + block_segs; - } + while (1) { - /* Convert to the disk's sector size */ - req->nr_512b_sectors = nr_sects; - nr_sects = (nr_sects << 9) >> xbb->sector_size_shift; + while (sg < last_block_sg) { + KASSERT(seg_idx < + XBB_MAX_SEGMENTS_PER_REQLIST, + ("seg_idx %d is too large, max " + "segs %d\n", seg_idx, + XBB_MAX_SEGMENTS_PER_REQLIST)); + + xbb_sg->first_sect = sg->first_sect; + xbb_sg->last_sect = sg->last_sect; + xbb_sg->nsect = + (int8_t)(sg->last_sect - + sg->first_sect + 1); - if ((req->nr_512b_sectors & ((xbb->sector_size >> 9) - 1)) != 0) { - device_printf(xbb->dev, "%s: I/O size (%d) is not a multiple " - "of the backing store sector size (%d)\n", - __func__, req->nr_512b_sectors << 9, - xbb->sector_size); - goto fail_send_response; + if ((sg->last_sect >= (PAGE_SIZE >> 9)) + || (xbb_sg->nsect <= 0)) { + reqlist->status = BLKIF_RSP_ERROR; + goto send_response; + } + + nr_sects += xbb_sg->nsect; + map->host_addr = xbb_get_gntaddr(reqlist, + seg_idx, /*sector*/0); + KASSERT(map->host_addr + PAGE_SIZE <= + xbb->ring_config.gnt_addr, + ("Host address %#jx len %d overlaps " + "ring address %#jx\n", + (uintmax_t)map->host_addr, PAGE_SIZE, + (uintmax_t)xbb->ring_config.gnt_addr)); + + map->flags = GNTMAP_host_map; + map->ref = sg->gref; + map->dom = xbb->otherend_id; + if (operation == BIO_WRITE) + map->flags |= GNTMAP_readonly; + sg++; + map++; + xbb_sg++; + seg_idx++; + req_seg_idx++; + } + + block_segs = MIN(nseg - req_seg_idx, + BLKIF_MAX_SEGMENTS_PER_SEGMENT_BLOCK); + if (block_segs == 0) + break; + + /* + * Fetch the next request block full of SG elements. + * For now, only the spacing between entries is + * different in the different ABIs, not the sg entry + * layout. + */ + req_ring_idx++; + switch (xbb->abi) { + case BLKIF_PROTOCOL_NATIVE: + sg = BLKRING_GET_SG_REQUEST(&xbb->rings.native, + req_ring_idx); + break; + case BLKIF_PROTOCOL_X86_32: + { + sg = BLKRING_GET_SG_REQUEST(&xbb->rings.x86_32, + req_ring_idx); + break; + } + case BLKIF_PROTOCOL_X86_64: + { + sg = BLKRING_GET_SG_REQUEST(&xbb->rings.x86_64, + req_ring_idx); + break; + } + default: + panic("Unexpected blkif protocol ABI."); + /* NOTREACHED */ + } + last_block_sg = sg + block_segs; + } + + /* Convert to the disk's sector size */ + nreq->nr_512b_sectors = nr_sects; + nr_sects = (nr_sects << 9) >> xbb->sector_size_shift; + total_sects += nr_sects; + + if ((nreq->nr_512b_sectors & + ((xbb->sector_size >> 9) - 1)) != 0) { + device_printf(xbb->dev, "%s: I/O size (%d) is not " + "a multiple of the backing store sector " + "size (%d)\n", __func__, + nreq->nr_512b_sectors << 9, + xbb->sector_size); + reqlist->status = BLKIF_RSP_ERROR; + goto send_response; + } } error = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, - maps, req->nr_pages); + xbb->maps, reqlist->nr_segments); if (error != 0) panic("Grant table operation failed (%d)", error); - for (seg_idx = 0, map = maps; seg_idx < nseg; seg_idx++, map++) { + reqlist->flags |= XBB_REQLIST_MAPPED; + + for (seg_idx = 0, map = xbb->maps; seg_idx < reqlist->nr_segments; + seg_idx++, map++){ if (unlikely(map->status != 0)) { - DPRINTF("invalid buffer -- could not remap it (%d)\n", - map->status); - DPRINTF("Mapping(%d): Host Addr 0x%lx, flags 0x%x " - "ref 0x%x, dom %d\n", seg_idx, + DPRINTF("invalid buffer -- could not remap " + "it (%d)\n", map->status); + DPRINTF("Mapping(%d): Host Addr 0x%lx, flags " + "0x%x ref 0x%x, dom %d\n", seg_idx, map->host_addr, map->flags, map->ref, map->dom); - goto fail_unmap_req; + reqlist->status = BLKIF_RSP_ERROR; + goto send_response; } - req->gnt_handles[seg_idx] = map->handle; + reqlist->gnt_handles[seg_idx] = map->handle; } - if (ring_req->sector_number + nr_sects > xbb->media_num_sectors) { + if (reqlist->starting_sector_number + total_sects > + xbb->media_num_sectors) { DPRINTF("%s of [%" PRIu64 ",%" PRIu64 "] " "extends past end of device %s\n", operation == BIO_READ ? "read" : "write", - ring_req->sector_number, - ring_req->sector_number + nr_sects, xbb->dev_name); - goto fail_unmap_req; + reqlist->starting_sector_number, + reqlist->starting_sector_number + total_sects, + xbb->dev_name); + reqlist->status = BLKIF_RSP_ERROR; + goto send_response; } do_dispatch: error = xbb->dispatch_io(xbb, - ring_req, - req, - nseg, + reqlist, operation, bio_flags); if (error != 0) { - if (operation == BIO_FLUSH) - goto fail_send_response; - else - goto fail_unmap_req; + reqlist->status = BLKIF_RSP_ERROR; + goto send_response; } - return; + return (0); +send_response: -fail_unmap_req: - xbb_unmap_req(req); - /* FALLTHROUGH */ + xbb_complete_reqlist(xbb, reqlist); -fail_send_response: - xbb_send_response(xbb, req, BLKIF_RSP_ERROR); - xbb_release_req(xbb, req); - devstat_end_transaction(xbb->xbb_stats, - /*bytes*/0, - req->ds_tag_type, - req->ds_trans_type, - /*now*/NULL, - /*then*/&req->ds_t0); + return (0); +} + +static __inline int +xbb_count_sects(blkif_request_t *ring_req) +{ + int i; + int cur_size = 0; + + for (i = 0; i < ring_req->nr_segments; i++) { + int nsect; + + nsect = (int8_t)(ring_req->seg[i].last_sect - + ring_req->seg[i].first_sect + 1); + if (nsect <= 0) + break; + + cur_size += nsect; + } + + return (cur_size); } /** @@ -1172,95 +1809,210 @@ fail_send_response: static void xbb_run_queue(void *context, int pending) { - struct xbb_softc *xbb; - blkif_back_rings_t *rings; - RING_IDX rp; + struct xbb_softc *xbb; + blkif_back_rings_t *rings; + RING_IDX rp; + uint64_t cur_sector; + int cur_operation; + struct xbb_xen_reqlist *reqlist; - xbb = (struct xbb_softc *)context; - rings = &xbb->rings; + xbb = (struct xbb_softc *)context; + rings = &xbb->rings; /* - * Cache req_prod to avoid accessing a cache line shared - * with the frontend. - */ - rp = rings->common.sring->req_prod; - - /* Ensure we see queued requests up to 'rp'. */ - rmb(); - - /** - * Run so long as there is work to consume and the generation - * of a response will not overflow the ring. + * Work gather and dispatch loop. Note that we have a bias here + * towards gathering I/O sent by blockfront. We first gather up + * everything in the ring, as long as we have resources. Then we + * dispatch one request, and then attempt to gather up any + * additional requests that have come in while we were dispatching + * the request. * - * @note There's a 1 to 1 relationship between requests and responses, - * so an overflow should never occur. This test is to protect - * our domain from digesting bogus data. Shouldn't we log this? + * This allows us to get a clearer picture (via devstat) of how + * many requests blockfront is queueing to us at any given time. */ - while (rings->common.req_cons != rp - && RING_REQUEST_CONS_OVERFLOW(&rings->common, - rings->common.req_cons) == 0) { - blkif_request_t ring_req_storage; - blkif_request_t *ring_req; - struct xbb_xen_req *req; - RING_IDX req_ring_idx; + for (;;) { + int retval; + + /* + * Initialize reqlist to the last element in the pending + * queue, if there is one. This allows us to add more + * requests to that request list, if we have room. + */ + reqlist = STAILQ_LAST(&xbb->reqlist_pending_stailq, + xbb_xen_reqlist, links); + if (reqlist != NULL) { + cur_sector = reqlist->next_contig_sector; + cur_operation = reqlist->operation; + } else { + cur_operation = 0; + cur_sector = 0; + } + + /* + * Cache req_prod to avoid accessing a cache line shared + * with the frontend. + */ + rp = rings->common.sring->req_prod; + + /* Ensure we see queued requests up to 'rp'. */ + rmb(); + + /** + * Run so long as there is work to consume and the generation + * of a response will not overflow the ring. + * + * @note There's a 1 to 1 relationship between requests and + * responses, so an overflow should never occur. This + * test is to protect our domain from digesting bogus + * data. Shouldn't we log this? + */ + while (rings->common.req_cons != rp + && RING_REQUEST_CONS_OVERFLOW(&rings->common, + rings->common.req_cons) == 0){ + blkif_request_t ring_req_storage; + blkif_request_t *ring_req; + int cur_size; + + switch (xbb->abi) { + case BLKIF_PROTOCOL_NATIVE: + ring_req = RING_GET_REQUEST(&xbb->rings.native, + rings->common.req_cons); + break; + case BLKIF_PROTOCOL_X86_32: + { + struct blkif_x86_32_request *ring_req32; + + ring_req32 = RING_GET_REQUEST( + &xbb->rings.x86_32, rings->common.req_cons); + blkif_get_x86_32_req(&ring_req_storage, + ring_req32); + ring_req = &ring_req_storage; + break; + } + case BLKIF_PROTOCOL_X86_64: + { + struct blkif_x86_64_request *ring_req64; + + ring_req64 =RING_GET_REQUEST(&xbb->rings.x86_64, + rings->common.req_cons); + blkif_get_x86_64_req(&ring_req_storage, + ring_req64); + ring_req = &ring_req_storage; + break; + } + default: + panic("Unexpected blkif protocol ABI."); + /* NOTREACHED */ + } - req = xbb_get_req(xbb); - if (req == NULL) { /* - * Resource shortage has been recorded. - * We'll be scheduled to run once a request - * object frees up due to a completion. + * Check for situations that would require closing + * off this I/O for further coalescing: + * - Coalescing is turned off. + * - Current I/O is out of sequence with the previous + * I/O. + * - Coalesced I/O would be too large. + */ + if ((reqlist != NULL) + && ((xbb->no_coalesce_reqs != 0) + || ((xbb->no_coalesce_reqs == 0) + && ((ring_req->sector_number != cur_sector) + || (ring_req->operation != cur_operation) + || ((ring_req->nr_segments + reqlist->nr_segments) > + xbb->max_reqlist_segments))))) { + reqlist = NULL; + } + + /* + * Grab and check for all resources in one shot. + * If we can't get all of the resources we need, + * the shortage is noted and the thread will get + * woken up when more resources are available. + */ + retval = xbb_get_resources(xbb, &reqlist, ring_req, + xbb->rings.common.req_cons); + + if (retval != 0) { + /* + * Resource shortage has been recorded. + * We'll be scheduled to run once a request + * object frees up due to a completion. + */ + break; + } + + /* + * Signify that we can overwrite this request with + * a response by incrementing our consumer index. + * The response won't be generated until after + * we've already consumed all necessary data out + * of the version of the request in the ring buffer + * (for native mode). We must update the consumer + * index before issueing back-end I/O so there is + * no possibility that it will complete and a + * response be generated before we make room in + * the queue for that response. + */ + xbb->rings.common.req_cons += + BLKIF_SEGS_TO_BLOCKS(ring_req->nr_segments); + xbb->reqs_received++; + + cur_size = xbb_count_sects(ring_req); + cur_sector = ring_req->sector_number + cur_size; + reqlist->next_contig_sector = cur_sector; + cur_operation = ring_req->operation; + } + + /* Check for I/O to dispatch */ + reqlist = STAILQ_FIRST(&xbb->reqlist_pending_stailq); + if (reqlist == NULL) { + /* + * We're out of work to do, put the task queue to + * sleep. */ break; } - switch (xbb->abi) { - case BLKIF_PROTOCOL_NATIVE: - ring_req = RING_GET_REQUEST(&xbb->rings.native, - rings->common.req_cons); - break; - case BLKIF_PROTOCOL_X86_32: - { - struct blkif_x86_32_request *ring_req32; - - ring_req32 = RING_GET_REQUEST(&xbb->rings.x86_32, - rings->common.req_cons); - blkif_get_x86_32_req(&ring_req_storage, ring_req32); - ring_req = &ring_req_storage; - break; - } - case BLKIF_PROTOCOL_X86_64: - { - struct blkif_x86_64_request *ring_req64; - - ring_req64 = RING_GET_REQUEST(&xbb->rings.x86_64, - rings->common.req_cons); - blkif_get_x86_64_req(&ring_req_storage, ring_req64); - ring_req = &ring_req_storage; - break; - } - default: - panic("Unexpected blkif protocol ABI."); - /* NOTREACHED */ - } - /* - * Signify that we can overwrite this request with a - * response by incrementing our consumer index. The - * response won't be generated until after we've already - * consumed all necessary data out of the version of the - * request in the ring buffer (for native mode). We - * must update the consumer index before issueing back-end - * I/O so there is no possibility that it will complete - * and a response be generated before we make room in - * the queue for that response. + * Grab the first request off the queue and attempt + * to dispatch it. */ - req_ring_idx = xbb->rings.common.req_cons; - xbb->rings.common.req_cons += - BLKIF_SEGS_TO_BLOCKS(ring_req->nr_segments); + STAILQ_REMOVE_HEAD(&xbb->reqlist_pending_stailq, links); - xbb_dispatch_io(xbb, ring_req, req, req_ring_idx); + retval = xbb_dispatch_io(xbb, reqlist); + if (retval != 0) { + /* + * xbb_dispatch_io() returns non-zero only when + * there is a resource shortage. If that's the + * case, re-queue this request on the head of the + * queue, and go to sleep until we have more + * resources. + */ + STAILQ_INSERT_HEAD(&xbb->reqlist_pending_stailq, + reqlist, links); + break; + } else { + /* + * If we still have anything on the queue after + * removing the head entry, that is because we + * met one of the criteria to create a new + * request list (outlined above), and we'll call + * that a forced dispatch for statistical purposes. + * + * Otherwise, if there is only one element on the + * queue, we coalesced everything available on + * the ring and we'll call that a normal dispatch. + */ + reqlist = STAILQ_FIRST(&xbb->reqlist_pending_stailq); + + if (reqlist != NULL) + xbb->forced_dispatch++; + else + xbb->normal_dispatch++; + + xbb->total_dispatch++; + } } } @@ -1285,11 +2037,7 @@ xbb_intr(void *arg) * Backend handler for character device access. * * \param xbb Per-instance xbb configuration structure. - * \param ring_req Front-end's I/O request as pulled from the shared - * communication ring. - * \param req Allocated internal request structure. - * \param nseg The number of valid segments for this request in - * xbb->xbb_sgs. + * \param reqlist Allocated internal request list structure. * \param operation BIO_* I/O operation code. * \param bio_flags Additional bio_flag data to pass to any generated * bios (e.g. BIO_ORDERED).. @@ -1297,28 +2045,30 @@ xbb_intr(void *arg) * \return 0 for success, errno codes for failure. */ static int -xbb_dispatch_dev(struct xbb_softc *xbb, blkif_request_t *ring_req, - struct xbb_xen_req *req, int nseg, int operation, - int bio_flags) +xbb_dispatch_dev(struct xbb_softc *xbb, struct xbb_xen_reqlist *reqlist, + int operation, int bio_flags) { struct xbb_dev_data *dev_data; - struct bio *bios[XBB_MAX_SEGMENTS_PER_REQUEST]; + struct bio *bios[XBB_MAX_SEGMENTS_PER_REQLIST]; + struct xbb_xen_req *nreq; off_t bio_offset; struct bio *bio; struct xbb_sg *xbb_sg; u_int nbio; u_int bio_idx; + u_int nseg; u_int seg_idx; int error; dev_data = &xbb->backend.dev; - bio_offset = (off_t)ring_req->sector_number + bio_offset = (off_t)reqlist->starting_sector_number << xbb->sector_size_shift; error = 0; nbio = 0; bio_idx = 0; if (operation == BIO_FLUSH) { + nreq = STAILQ_FIRST(&reqlist->contig_req_list); bio = g_new_bio(); if (unlikely(bio == NULL)) { DPRINTF("Unable to allocate bio for BIO_FLUSH\n"); @@ -1332,19 +2082,21 @@ xbb_dispatch_dev(struct xbb_softc *xbb, blkif_request_t *ring_req, bio->bio_offset = 0; bio->bio_data = 0; bio->bio_done = xbb_bio_done; - bio->bio_caller1 = req; + bio->bio_caller1 = nreq; bio->bio_pblkno = 0; - req->pendcnt = 1; + nreq->pendcnt = 1; - (*dev_data->csw->d_strategy)(bios[bio_idx]); + (*dev_data->csw->d_strategy)(bio); return (0); } - for (seg_idx = 0, bio = NULL, xbb_sg = xbb->xbb_sgs; - seg_idx < nseg; - seg_idx++, xbb_sg++) { + xbb_sg = xbb->xbb_sgs; + bio = NULL; + nseg = reqlist->nr_segments; + + for (seg_idx = 0; seg_idx < nseg; seg_idx++, xbb_sg++) { /* * KVA will not be contiguous, so any additional @@ -1353,10 +2105,10 @@ xbb_dispatch_dev(struct xbb_softc *xbb, blkif_request_t *ring_req, if ((bio != NULL) && (xbb_sg->first_sect != 0)) { if ((bio->bio_length & (xbb->sector_size - 1)) != 0) { - printf("%s: Discontiguous I/O request from " - "domain %d ends on non-sector " - "boundary\n", __func__, - xbb->otherend_id); + printf("%s: Discontiguous I/O request " + "from domain %d ends on " + "non-sector boundary\n", + __func__, xbb->otherend_id); error = EINVAL; goto fail_free_bios; } @@ -1365,12 +2117,12 @@ xbb_dispatch_dev(struct xbb_softc *xbb, blkif_request_t *ring_req, if (bio == NULL) { /* - * Make sure that the start of this bio is aligned - * to a device sector. + * Make sure that the start of this bio is + * aligned to a device sector. */ - if ((bio_offset & (xbb->sector_size - 1)) != 0) { - printf("%s: Misaligned I/O request from " - "domain %d\n", __func__, + if ((bio_offset & (xbb->sector_size - 1)) != 0){ + printf("%s: Misaligned I/O request " + "from domain %d\n", __func__, xbb->otherend_id); error = EINVAL; goto fail_free_bios; @@ -1385,12 +2137,11 @@ xbb_dispatch_dev(struct xbb_softc *xbb, blkif_request_t *ring_req, bio->bio_flags |= bio_flags; bio->bio_dev = dev_data->cdev; bio->bio_offset = bio_offset; - bio->bio_data = xbb_req_ioaddr(req, seg_idx, - xbb_sg->first_sect); + bio->bio_data = xbb_reqlist_ioaddr(reqlist, seg_idx, + xbb_sg->first_sect); bio->bio_done = xbb_bio_done; - bio->bio_caller1 = req; - bio->bio_pblkno = bio_offset - >> xbb->sector_size_shift; + bio->bio_caller1 = reqlist; + bio->bio_pblkno = bio_offset >> xbb->sector_size_shift; } bio->bio_length += xbb_sg->nsect << 9; @@ -1400,10 +2151,10 @@ xbb_dispatch_dev(struct xbb_softc *xbb, blkif_request_t *ring_req, if (xbb_sg->last_sect != (PAGE_SIZE - 512) >> 9) { if ((bio->bio_length & (xbb->sector_size - 1)) != 0) { - printf("%s: Discontiguous I/O request from " - "domain %d ends on non-sector " - "boundary\n", __func__, - xbb->otherend_id); + printf("%s: Discontiguous I/O request " + "from domain %d ends on " + "non-sector boundary\n", + __func__, xbb->otherend_id); error = EINVAL; goto fail_free_bios; } @@ -1415,7 +2166,7 @@ xbb_dispatch_dev(struct xbb_softc *xbb, blkif_request_t *ring_req, } } - req->pendcnt = nbio; + reqlist->pendcnt = nbio; for (bio_idx = 0; bio_idx < nbio; bio_idx++) { @@ -1423,10 +2174,10 @@ xbb_dispatch_dev(struct xbb_softc *xbb, blkif_request_t *ring_req, vm_offset_t kva_offset; kva_offset = (vm_offset_t)bios[bio_idx]->bio_data - - (vm_offset_t)req->bounce; + - (vm_offset_t)reqlist->bounce; if (operation == BIO_WRITE) { memcpy(bios[bio_idx]->bio_data, - (uint8_t *)req->kva + kva_offset, + (uint8_t *)reqlist->kva + kva_offset, bios[bio_idx]->bio_bcount); } #endif @@ -1438,7 +2189,7 @@ xbb_dispatch_dev(struct xbb_softc *xbb, blkif_request_t *ring_req, fail_free_bios: for (bio_idx = 0; bio_idx < (nbio-1); bio_idx++) g_destroy_bio(bios[bio_idx]); - + return (error); } @@ -1446,24 +2197,21 @@ fail_free_bios: * Backend handler for file access. * * \param xbb Per-instance xbb configuration structure. - * \param ring_req Front-end's I/O request as pulled from the shared - * communication ring. - * \param req Allocated internal request structure. - * \param nseg The number of valid segments for this request in - * xbb->xbb_sgs. + * \param reqlist Allocated internal request list. * \param operation BIO_* I/O operation code. - * \param bio_flags Additional bio_flag data to pass to any generated bios + * \param flags Additional bio_flag data to pass to any generated bios * (e.g. BIO_ORDERED).. * * \return 0 for success, errno codes for failure. */ static int -xbb_dispatch_file(struct xbb_softc *xbb, blkif_request_t *ring_req, - struct xbb_xen_req *req, int nseg, int operation, - int flags) +xbb_dispatch_file(struct xbb_softc *xbb, struct xbb_xen_reqlist *reqlist, + int operation, int flags) { struct xbb_file_data *file_data; u_int seg_idx; + u_int nseg; + off_t sectors_sent; struct uio xuio; struct xbb_sg *xbb_sg; struct iovec *xiovec; @@ -1475,11 +2223,10 @@ xbb_dispatch_file(struct xbb_softc *xbb, blkif_request_t *ring_req, int error; file_data = &xbb->backend.file; + sectors_sent = 0; error = 0; bzero(&xuio, sizeof(xuio)); - req->pendcnt = 0; - switch (operation) { case BIO_READ: xuio.uio_rw = UIO_READ; @@ -1509,37 +2256,39 @@ xbb_dispatch_file(struct xbb_softc *xbb, blkif_request_t *ring_req, panic("invalid operation %d", operation); /* NOTREACHED */ } - xuio.uio_offset = (vm_offset_t)ring_req->sector_number + xuio.uio_offset = (vm_offset_t)reqlist->starting_sector_number << xbb->sector_size_shift; - xuio.uio_segflg = UIO_SYSSPACE; xuio.uio_iov = file_data->xiovecs; xuio.uio_iovcnt = 0; + xbb_sg = xbb->xbb_sgs; + nseg = reqlist->nr_segments; - for (seg_idx = 0, xiovec = NULL, xbb_sg = xbb->xbb_sgs; - seg_idx < nseg; seg_idx++, xbb_sg++) { + for (xiovec = NULL, seg_idx = 0; seg_idx < nseg; seg_idx++, xbb_sg++) { /* - * If the first sector is not 0, the KVA will not be - * contiguous and we'll need to go on to another segment. + * If the first sector is not 0, the KVA will + * not be contiguous and we'll need to go on + * to another segment. */ if (xbb_sg->first_sect != 0) xiovec = NULL; if (xiovec == NULL) { xiovec = &file_data->xiovecs[xuio.uio_iovcnt]; - xiovec->iov_base = xbb_req_ioaddr(req, seg_idx, - xbb_sg->first_sect); + xiovec->iov_base = xbb_reqlist_ioaddr(reqlist, + seg_idx, xbb_sg->first_sect); #ifdef XBB_USE_BOUNCE_BUFFERS /* - * Store the address of the incoming buffer at this - * particular offset as well, so we can do the copy - * later without having to do more work to - * recalculate this address. + * Store the address of the incoming + * buffer at this particular offset + * as well, so we can do the copy + * later without having to do more + * work to recalculate this address. */ p_vaddr = &file_data->xiovecs_vaddr[xuio.uio_iovcnt]; - *p_vaddr = xbb_req_vaddr(req, seg_idx, - xbb_sg->first_sect); + *p_vaddr = xbb_reqlist_vaddr(reqlist, seg_idx, + xbb_sg->first_sect); #endif /* XBB_USE_BOUNCE_BUFFERS */ xiovec->iov_len = 0; xuio.uio_iovcnt++; @@ -1550,9 +2299,9 @@ xbb_dispatch_file(struct xbb_softc *xbb, blkif_request_t *ring_req, xuio.uio_resid += xbb_sg->nsect << 9; /* - * If the last sector is not the full page size count, - * the next segment will not be contiguous in KVA and we - * need a new iovec. + * If the last sector is not the full page + * size count, the next segment will not be + * contiguous in KVA and we need a new iovec. */ if (xbb_sg->last_sect != (PAGE_SIZE - 512) >> 9) xiovec = NULL; @@ -1676,23 +2425,10 @@ xbb_dispatch_file(struct xbb_softc *xbb, blkif_request_t *ring_req, bailout_send_response: - /* - * All I/O is already done, send the response. A lock is not - * necessary here because we're single threaded, and therefore the - * only context accessing this request right now. If that changes, - * we may need some locking here. - */ - xbb_unmap_req(req); - xbb_send_response(xbb, req, (error == 0) ? BLKIF_RSP_OKAY : - BLKIF_RSP_ERROR); - devstat_end_transaction(xbb->xbb_stats, - /*bytes*/error == 0 ? req->nr_512b_sectors << 9 - : 0, - req->ds_tag_type, - req->ds_trans_type, - /*now*/NULL, - /*then*/&req->ds_t0); - xbb_release_req(xbb, req); + if (error != 0) + reqlist->status = BLKIF_RSP_ERROR; + + xbb_complete_reqlist(xbb, reqlist); return (0); } @@ -1913,6 +2649,12 @@ xbb_open_backend(struct xbb_softc *xbb) DPRINTF("opening dev=%s\n", xbb->dev_name); + if (rootvnode == NULL) { + xenbus_dev_fatal(xbb->dev, ENOENT, + "Root file system not mounted"); + return (ENOENT); + } + if ((xbb->flags & XBBF_READ_ONLY) == 0) flags |= FWRITE; @@ -1996,11 +2738,39 @@ xbb_open_backend(struct xbb_softc *xbb) /*------------------------ Inter-Domain Communication ------------------------*/ /** - * Cleanup all inter-domain communication mechanisms. + * Free dynamically allocated KVA or pseudo-physical address allocations. * * \param xbb Per-instance xbb configuration structure. */ static void +xbb_free_communication_mem(struct xbb_softc *xbb) +{ + if (xbb->kva != 0) { +#ifndef XENHVM + kmem_free(kernel_map, xbb->kva, xbb->kva_size); +#else + if (xbb->pseudo_phys_res != NULL) { + bus_release_resource(xbb->dev, SYS_RES_MEMORY, + xbb->pseudo_phys_res_id, + xbb->pseudo_phys_res); + xbb->pseudo_phys_res = NULL; + } +#endif + } + xbb->kva = 0; + xbb->gnt_base_addr = 0; + if (xbb->kva_free != NULL) { + free(xbb->kva_free, M_XENBLOCKBACK); + xbb->kva_free = NULL; + } +} + +/** + * Cleanup all inter-domain communication mechanisms. + * + * \param xbb Per-instance xbb configuration structure. + */ +static int xbb_disconnect(struct xbb_softc *xbb) { struct gnttab_unmap_grant_ref ops[XBB_MAX_RING_PAGES]; @@ -2011,13 +2781,24 @@ xbb_disconnect(struct xbb_softc *xbb) DPRINTF("\n"); if ((xbb->flags & XBBF_RING_CONNECTED) == 0) - return; + return (0); if (xbb->irq != 0) { unbind_from_irqhandler(xbb->irq); xbb->irq = 0; } + mtx_unlock(&xbb->lock); + taskqueue_drain(xbb->io_taskqueue, &xbb->io_task); + mtx_lock(&xbb->lock); + + /* + * No new interrupts can generate work, but we must wait + * for all currently active requests to drain. + */ + if (xbb->active_request_count != 0) + return (EAGAIN); + for (ring_idx = 0, op = ops; ring_idx < xbb->ring_config.ring_pages; ring_idx++, op++) { @@ -2033,7 +2814,37 @@ xbb_disconnect(struct xbb_softc *xbb) if (error != 0) panic("Grant table op failed (%d)", error); + xbb_free_communication_mem(xbb); + + if (xbb->requests != NULL) { + free(xbb->requests, M_XENBLOCKBACK); + xbb->requests = NULL; + } + + if (xbb->request_lists != NULL) { + struct xbb_xen_reqlist *reqlist; + int i; + + /* There is one request list for ever allocated request. */ + for (i = 0, reqlist = xbb->request_lists; + i < xbb->max_requests; i++, reqlist++){ +#ifdef XBB_USE_BOUNCE_BUFFERS + if (reqlist->bounce != NULL) { + free(reqlist->bounce, M_XENBLOCKBACK); + reqlist->bounce = NULL; + } +#endif + if (reqlist->gnt_handles != NULL) { + free(reqlist->gnt_handles, M_XENBLOCKBACK); + reqlist->gnt_handles = NULL; + } + } + free(xbb->request_lists, M_XENBLOCKBACK); + xbb->request_lists = NULL; + } + xbb->flags &= ~XBBF_RING_CONNECTED; + return (0); } /** @@ -2135,7 +2946,7 @@ xbb_connect_ring(struct xbb_softc *xbb) INTR_TYPE_BIO | INTR_MPSAFE, &xbb->irq); if (error) { - xbb_disconnect(xbb); + (void)xbb_disconnect(xbb); xenbus_dev_fatal(xbb->dev, error, "binding event channel"); return (error); } @@ -2145,6 +2956,10 @@ xbb_connect_ring(struct xbb_softc *xbb) return 0; } +/* Needed to make bit_alloc() macro work */ +#define calloc(count, size) malloc((count)*(size), M_XENBLOCKBACK, \ + M_NOWAIT|M_ZERO); + /** * Size KVA and pseudo-physical address allocations based on negotiated * values for the size and number of I/O requests, and the size of our @@ -2158,9 +2973,18 @@ xbb_connect_ring(struct xbb_softc *xbb) static int xbb_alloc_communication_mem(struct xbb_softc *xbb) { - xbb->kva_size = (xbb->ring_config.ring_pages - + (xbb->max_requests * xbb->max_request_segments)) - * PAGE_SIZE; + xbb->reqlist_kva_pages = xbb->max_requests * xbb->max_request_segments; + xbb->reqlist_kva_size = xbb->reqlist_kva_pages * PAGE_SIZE; + xbb->kva_size = xbb->reqlist_kva_size + + (xbb->ring_config.ring_pages * PAGE_SIZE); + + xbb->kva_free = bit_alloc(xbb->reqlist_kva_pages); + if (xbb->kva_free == NULL) + return (ENOMEM); + + DPRINTF("%s: kva_size = %d, reqlist_kva_size = %d\n", + device_get_nameunit(xbb->dev), xbb->kva_size, + xbb->reqlist_kva_size); #ifndef XENHVM xbb->kva = kmem_alloc_nofault(kernel_map, xbb->kva_size); if (xbb->kva == 0) @@ -2185,31 +3009,11 @@ xbb_alloc_communication_mem(struct xbb_softc *xbb) xbb->kva = (vm_offset_t)rman_get_virtual(xbb->pseudo_phys_res); xbb->gnt_base_addr = rman_get_start(xbb->pseudo_phys_res); #endif /* XENHVM */ - return (0); -} -/** - * Free dynamically allocated KVA or pseudo-physical address allocations. - * - * \param xbb Per-instance xbb configuration structure. - */ -static void -xbb_free_communication_mem(struct xbb_softc *xbb) -{ - if (xbb->kva != 0) { -#ifndef XENHVM - kmem_free(kernel_map, xbb->kva, xbb->kva_size); -#else - if (xbb->pseudo_phys_res != NULL) { - bus_release_resource(xbb->dev, SYS_RES_MEMORY, - xbb->pseudo_phys_res_id, - xbb->pseudo_phys_res); - xbb->pseudo_phys_res = NULL; - } -#endif - } - xbb->kva = 0; - xbb->gnt_base_addr = 0; + DPRINTF("%s: kva: %#jx, gnt_base_addr: %#jx\n", + device_get_nameunit(xbb->dev), (uintmax_t)xbb->kva, + (uintmax_t)xbb->gnt_base_addr); + return (0); } /** @@ -2227,6 +3031,14 @@ xbb_collect_frontend_info(struct xbb_softc *xbb) otherend_path = xenbus_get_otherend_path(xbb->dev); + /* + * Protocol defaults valid even if all negotiation fails. + */ + xbb->ring_config.ring_pages = 1; + xbb->max_requests = BLKIF_MAX_RING_REQUESTS(PAGE_SIZE); + xbb->max_request_segments = BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK; + xbb->max_request_size = xbb->max_request_segments * PAGE_SIZE; + /* * Mandatory data (used in all versions of the protocol) first. */ @@ -2255,19 +3067,19 @@ xbb_collect_frontend_info(struct xbb_softc *xbb) * tree. */ (void)xs_scanf(XST_NIL, otherend_path, - "ring-pages", NULL, "%" PRIu32, + "ring-pages", NULL, "%u", &xbb->ring_config.ring_pages); (void)xs_scanf(XST_NIL, otherend_path, - "max-requests", NULL, "%" PRIu32, + "max-requests", NULL, "%u", &xbb->max_requests); (void)xs_scanf(XST_NIL, otherend_path, - "max-request-segments", NULL, "%" PRIu32, + "max-request-segments", NULL, "%u", &xbb->max_request_segments); (void)xs_scanf(XST_NIL, otherend_path, - "max-request-size", NULL, "%" PRIu32, + "max-request-size", NULL, "%u", &xbb->max_request_size); if (xbb->ring_config.ring_pages > XBB_MAX_RING_PAGES) { @@ -2360,8 +3172,6 @@ xbb_alloc_requests(struct xbb_softc *xbb) { struct xbb_xen_req *req; struct xbb_xen_req *last_req; - uint8_t *req_kva; - u_long gnt_base; /* * Allocate request book keeping datastructures. @@ -2374,43 +3184,68 @@ xbb_alloc_requests(struct xbb_softc *xbb) return (ENOMEM); } - req_kva = (uint8_t *)xbb->kva; - gnt_base = xbb->gnt_base_addr; req = xbb->requests; last_req = &xbb->requests[xbb->max_requests - 1]; + STAILQ_INIT(&xbb->request_free_stailq); while (req <= last_req) { + STAILQ_INSERT_TAIL(&xbb->request_free_stailq, req, links); + req++; + } + return (0); +} + +static int +xbb_alloc_request_lists(struct xbb_softc *xbb) +{ + int i; + struct xbb_xen_reqlist *reqlist; + + /* + * If no requests can be merged, we need 1 request list per + * in flight request. + */ + xbb->request_lists = malloc(xbb->max_requests * + sizeof(*xbb->request_lists), M_XENBLOCKBACK, M_NOWAIT|M_ZERO); + if (xbb->request_lists == NULL) { + xenbus_dev_fatal(xbb->dev, ENOMEM, + "Unable to allocate request list structures"); + return (ENOMEM); + } + + STAILQ_INIT(&xbb->reqlist_free_stailq); + STAILQ_INIT(&xbb->reqlist_pending_stailq); + for (i = 0; i < xbb->max_requests; i++) { int seg; - req->xbb = xbb; - req->kva = req_kva; - req->gnt_handles = malloc(xbb->max_request_segments - * sizeof(*req->gnt_handles), - M_XENBLOCKBACK, M_NOWAIT|M_ZERO); - if (req->gnt_handles == NULL) { - xenbus_dev_fatal(xbb->dev, ENOMEM, - "Unable to allocate request " - "grant references"); - return (ENOMEM); - } + reqlist = &xbb->request_lists[i]; + + reqlist->xbb = xbb; + #ifdef XBB_USE_BOUNCE_BUFFERS - req->bounce = malloc(xbb->max_request_size, - M_XENBLOCKBACK, M_NOWAIT); - if (req->bounce == NULL) { + reqlist->bounce = malloc(xbb->max_reqlist_size, + M_XENBLOCKBACK, M_NOWAIT); + if (reqlist->bounce == NULL) { xenbus_dev_fatal(xbb->dev, ENOMEM, "Unable to allocate request " "bounce buffers"); return (ENOMEM); } #endif /* XBB_USE_BOUNCE_BUFFERS */ - req->gnt_base = gnt_base; - req_kva += xbb->max_request_segments * PAGE_SIZE; - gnt_base += xbb->max_request_segments * PAGE_SIZE; - SLIST_INSERT_HEAD(&xbb->request_free_slist, req, links); - for (seg = 0; seg < xbb->max_request_segments; seg++) - req->gnt_handles[seg] = GRANT_REF_INVALID; + reqlist->gnt_handles = malloc(xbb->max_reqlist_segments * + sizeof(*reqlist->gnt_handles), + M_XENBLOCKBACK, M_NOWAIT|M_ZERO); + if (reqlist->gnt_handles == NULL) { + xenbus_dev_fatal(xbb->dev, ENOMEM, + "Unable to allocate request " + "grant references"); + return (ENOMEM); + } - req++; + for (seg = 0; seg < xbb->max_reqlist_segments; seg++) + reqlist->gnt_handles[seg] = GRANT_REF_INVALID; + + STAILQ_INSERT_TAIL(&xbb->reqlist_free_stailq, reqlist, links); } return (0); } @@ -2491,6 +3326,22 @@ xbb_connect(struct xbb_softc *xbb) if (xbb_collect_frontend_info(xbb) != 0) return; + xbb->flags &= ~XBBF_SHUTDOWN; + + /* + * We limit the maximum number of reqlist segments to the maximum + * number of segments in the ring, or our absolute maximum, + * whichever is smaller. + */ + xbb->max_reqlist_segments = MIN(xbb->max_request_segments * + xbb->max_requests, XBB_MAX_SEGMENTS_PER_REQLIST); + + /* + * The maximum size is simply a function of the number of segments + * we can handle. + */ + xbb->max_reqlist_size = xbb->max_reqlist_segments * PAGE_SIZE; + /* Allocate resources whose size depends on front-end configuration. */ error = xbb_alloc_communication_mem(xbb); if (error != 0) { @@ -2505,6 +3356,12 @@ xbb_connect(struct xbb_softc *xbb) return; } + error = xbb_alloc_request_lists(xbb); + if (error != 0) { + /* Specific errors are reported by xbb_alloc_request_lists(). */ + return; + } + /* * Connect communication channel. */ @@ -2520,7 +3377,7 @@ xbb_connect(struct xbb_softc *xbb) * in this connection, and waiting for a front-end state * change will not help the situation. */ - xbb_disconnect(xbb); + (void)xbb_disconnect(xbb); return; } @@ -2542,7 +3399,7 @@ xbb_connect(struct xbb_softc *xbb) static int xbb_shutdown(struct xbb_softc *xbb) { - static int in_shutdown; + int error; DPRINTF("\n"); @@ -2553,7 +3410,7 @@ xbb_shutdown(struct xbb_softc *xbb) * the same time. Tell the caller that hits this * race to try back later. */ - if (in_shutdown != 0) + if ((xbb->flags & XBBF_IN_SHUTDOWN) != 0) return (EAGAIN); DPRINTF("\n"); @@ -2561,20 +3418,30 @@ xbb_shutdown(struct xbb_softc *xbb) /* Indicate shutdown is in progress. */ xbb->flags |= XBBF_SHUTDOWN; - /* Wait for requests to complete. */ - if (xbb->active_request_count != 0) - return (EAGAIN); - + /* Disconnect from the front-end. */ + error = xbb_disconnect(xbb); + if (error != 0) { + /* + * Requests still outstanding. We'll be called again + * once they complete. + */ + KASSERT(error == EAGAIN, + ("%s: Unexpected xbb_disconnect() failure %d", + __func__, error)); + + return (error); + } + DPRINTF("\n"); - /* Disconnect from the front-end. */ - xbb_disconnect(xbb); - - in_shutdown = 1; + xbb->flags |= XBBF_IN_SHUTDOWN; mtx_unlock(&xbb->lock); - xenbus_set_state(xbb->dev, XenbusStateClosed); + + if (xenbus_get_state(xbb->dev) < XenbusStateClosing) + xenbus_set_state(xbb->dev, XenbusStateClosing); + mtx_lock(&xbb->lock); - in_shutdown = 0; + xbb->flags &= ~XBBF_IN_SHUTDOWN; /* Indicate to xbb_detach() that is it safe to proceed. */ wakeup(xbb); @@ -2633,6 +3500,77 @@ xbb_probe(device_t dev) return (ENXIO); } +/** + * Setup sysctl variables to control various Block Back parameters. + * + * \param xbb Xen Block Back softc. + * + */ +static void +xbb_setup_sysctl(struct xbb_softc *xbb) +{ + struct sysctl_ctx_list *sysctl_ctx = NULL; + struct sysctl_oid *sysctl_tree = NULL; + + sysctl_ctx = device_get_sysctl_ctx(xbb->dev); + if (sysctl_ctx == NULL) + return; + + sysctl_tree = device_get_sysctl_tree(xbb->dev); + if (sysctl_tree == NULL) + return; + + SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, + "disable_flush", CTLFLAG_RW, &xbb->disable_flush, 0, + "fake the flush command"); + + SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, + "flush_interval", CTLFLAG_RW, &xbb->flush_interval, 0, + "send a real flush for N flush requests"); + + SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, + "no_coalesce_reqs", CTLFLAG_RW, &xbb->no_coalesce_reqs,0, + "Don't coalesce contiguous requests"); + + SYSCTL_ADD_UQUAD(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, + "reqs_received", CTLFLAG_RW, &xbb->reqs_received, + "how many I/O requests we have received"); + + SYSCTL_ADD_UQUAD(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, + "reqs_completed", CTLFLAG_RW, &xbb->reqs_completed, + "how many I/O requests have been completed"); + + SYSCTL_ADD_UQUAD(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, + "forced_dispatch", CTLFLAG_RW, &xbb->forced_dispatch, + "how many I/O dispatches were forced"); + + SYSCTL_ADD_UQUAD(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, + "normal_dispatch", CTLFLAG_RW, &xbb->normal_dispatch, + "how many I/O dispatches were normal"); + + SYSCTL_ADD_UQUAD(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, + "total_dispatch", CTLFLAG_RW, &xbb->total_dispatch, + "total number of I/O dispatches"); + + SYSCTL_ADD_UQUAD(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, + "kva_shortages", CTLFLAG_RW, &xbb->kva_shortages, + "how many times we have run out of KVA"); + + SYSCTL_ADD_UQUAD(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, + "request_shortages", CTLFLAG_RW, + &xbb->request_shortages, + "how many times we have run out of requests"); + + SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, + "max_requests", CTLFLAG_RD, &xbb->max_requests, 0, + "maximum outstanding requests (negotiated)"); + + SYSCTL_ADD_UINT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, + "max_request_segments", CTLFLAG_RD, + &xbb->max_request_segments, 0, + "maximum number of pages per requests (negotiated)"); +} + /** * Attach to a XenBus device that has been claimed by our probe routine. * @@ -2643,8 +3581,8 @@ xbb_probe(device_t dev) static int xbb_attach(device_t dev) { - struct xbb_softc *xbb; - int error; + struct xbb_softc *xbb; + int error; DPRINTF("Attaching to %s\n", xenbus_get_node(dev)); @@ -2658,15 +3596,6 @@ xbb_attach(device_t dev) xbb->otherend_id = xenbus_get_otherend_id(dev); TASK_INIT(&xbb->io_task, /*priority*/0, xbb_run_queue, xbb); mtx_init(&xbb->lock, device_get_nameunit(dev), NULL, MTX_DEF); - SLIST_INIT(&xbb->request_free_slist); - - /* - * Protocol defaults valid even if all negotiation fails. - */ - xbb->ring_config.ring_pages = 1; - xbb->max_requests = BLKIF_MAX_RING_REQUESTS(PAGE_SIZE); - xbb->max_request_segments = BLKIF_MAX_SEGMENTS_PER_HEADER_BLOCK; - xbb->max_request_size = xbb->max_request_segments * PAGE_SIZE; /* * Publish protocol capabilities for consumption by the @@ -2763,6 +3692,18 @@ xbb_attach(device_t dev) DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_OTHER, DEVSTAT_PRIORITY_OTHER); + + xbb->xbb_stats_in = devstat_new_entry("xbbi", device_get_unit(xbb->dev), + xbb->sector_size, + DEVSTAT_ALL_SUPPORTED, + DEVSTAT_TYPE_DIRECT + | DEVSTAT_TYPE_IF_OTHER, + DEVSTAT_PRIORITY_OTHER); + /* + * Setup sysctl variables. + */ + xbb_setup_sysctl(xbb); + /* * Create a taskqueue for doing work that must occur from a * thread context. @@ -2797,7 +3738,7 @@ xbb_attach(device_t dev) } /** - * Detach from a block back device instanced. + * Detach from a block back device instance. * * \param dev NewBus device object representing this Xen Block Back instance. * @@ -2823,7 +3764,6 @@ xbb_detach(device_t dev) "xbb_shutdown", 0); } mtx_unlock(&xbb->lock); - mtx_destroy(&xbb->lock); DPRINTF("\n"); @@ -2833,8 +3773,10 @@ xbb_detach(device_t dev) if (xbb->xbb_stats != NULL) devstat_remove_entry(xbb->xbb_stats); + if (xbb->xbb_stats_in != NULL) + devstat_remove_entry(xbb->xbb_stats_in); + xbb_close_backend(xbb); - xbb_free_communication_mem(xbb); if (xbb->dev_mode != NULL) { free(xbb->dev_mode, M_XENBUS); @@ -2851,29 +3793,7 @@ xbb_detach(device_t dev) xbb->dev_name = NULL; } - if (xbb->requests != NULL) { - struct xbb_xen_req *req; - struct xbb_xen_req *last_req; - - req = xbb->requests; - last_req = &xbb->requests[xbb->max_requests - 1]; - while (req <= last_req) { -#ifdef XBB_USE_BOUNCE_BUFFERS - if (req->bounce != NULL) { - free(req->bounce, M_XENBLOCKBACK); - req->bounce = NULL; - } -#endif - if (req->gnt_handles != NULL) { - free (req->gnt_handles, M_XENBLOCKBACK); - req->gnt_handles = NULL; - } - req++; - } - free(xbb->requests, M_XENBLOCKBACK); - xbb->requests = NULL; - } - + mtx_destroy(&xbb->lock); return (0); } @@ -2926,22 +3846,24 @@ xbb_frontend_changed(device_t dev, XenbusState frontend_state) { struct xbb_softc *xbb = device_get_softc(dev); - DPRINTF("state=%s\n", xenbus_strstate(frontend_state)); + DPRINTF("frontend_state=%s, xbb_state=%s\n", + xenbus_strstate(frontend_state), + xenbus_strstate(xenbus_get_state(xbb->dev))); switch (frontend_state) { case XenbusStateInitialising: - case XenbusStateClosing: break; case XenbusStateInitialised: case XenbusStateConnected: xbb_connect(xbb); break; + case XenbusStateClosing: case XenbusStateClosed: - case XenbusStateInitWait: - mtx_lock(&xbb->lock); xbb_shutdown(xbb); mtx_unlock(&xbb->lock); + if (frontend_state == XenbusStateClosed) + xenbus_set_state(xbb->dev, XenbusStateClosed); break; default: xenbus_dev_fatal(xbb->dev, EINVAL, "saw state %d at frontend", diff --git a/sys/geom/geom.h b/sys/geom/geom.h index 1dc6eb11ef8..6256572a390 100644 --- a/sys/geom/geom.h +++ b/sys/geom/geom.h @@ -76,6 +76,7 @@ typedef void g_orphan_t (struct g_consumer *); typedef void g_start_t (struct bio *); typedef void g_spoiled_t (struct g_consumer *); +typedef void g_attrchanged_t (struct g_consumer *, const char *attr); typedef void g_dumpconf_t (struct sbuf *, const char *indent, struct g_geom *, struct g_consumer *, struct g_provider *); @@ -100,6 +101,7 @@ struct g_class { */ g_start_t *start; g_spoiled_t *spoiled; + g_attrchanged_t *attrchanged; g_dumpconf_t *dumpconf; g_access_t *access; g_orphan_t *orphan; @@ -128,6 +130,7 @@ struct g_geom { int rank; g_start_t *start; g_spoiled_t *spoiled; + g_attrchanged_t *attrchanged; g_dumpconf_t *dumpconf; g_access_t *access; g_orphan_t *orphan; @@ -217,6 +220,7 @@ struct g_classifier_hook { /* geom_dev.c */ struct cdev; void g_dev_print(void); +void g_dev_physpath_changed(void); struct g_provider *g_dev_getprovider(struct cdev *dev); /* geom_dump.c */ @@ -232,6 +236,7 @@ typedef void g_event_t(void *, int flag); int g_post_event(g_event_t *func, void *arg, int flag, ...); int g_waitfor_event(g_event_t *func, void *arg, int flag, ...); void g_cancel_event(void *ref); +int g_attr_changed(struct g_provider *pp, const char *attr, int flag); void g_orphan_provider(struct g_provider *pp, int error); void g_waitidlelock(void); diff --git a/sys/geom/geom_dev.c b/sys/geom/geom_dev.c index f291b32e194..210f2ee0441 100644 --- a/sys/geom/geom_dev.c +++ b/sys/geom/geom_dev.c @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -52,6 +53,12 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include + +/* + * Use the consumer private field to reference a physdev alias (if any). + */ +#define cp_alias_dev private static d_open_t g_dev_open; static d_close_t g_dev_close; @@ -72,12 +79,14 @@ static struct cdevsw g_dev_cdevsw = { static g_taste_t g_dev_taste; static g_orphan_t g_dev_orphan; +static g_attrchanged_t g_dev_attrchanged; static struct g_class g_dev_class = { .name = "DEV", .version = G_VERSION, .taste = g_dev_taste, .orphan = g_dev_orphan, + .attrchanged = g_dev_attrchanged }; void @@ -93,6 +102,40 @@ g_dev_print(void) printf("\n"); } +static void +g_dev_attrchanged(struct g_consumer *cp, const char *attr) +{ + + if (strcmp(attr, "GEOM::physpath") != 0) + return; + + if (g_access(cp, 1, 0, 0) == 0) { + char *physpath; + int error, physpath_len; + + physpath_len = MAXPATHLEN; + physpath = g_malloc(physpath_len, M_WAITOK|M_ZERO); + error = + g_io_getattr("GEOM::physpath", cp, &physpath_len, physpath); + g_access(cp, -1, 0, 0); + if (error == 0 && strlen(physpath) != 0) { + struct cdev *dev; + struct cdev *old_alias_dev; + struct cdev **alias_devp; + + dev = cp->geom->softc; + old_alias_dev = cp->cp_alias_dev; + alias_devp = (struct cdev **)&cp->cp_alias_dev; + make_dev_physpath_alias(MAKEDEV_WAITOK, alias_devp, + dev, old_alias_dev, physpath); + } else if (cp->cp_alias_dev) { + destroy_dev((struct cdev *)cp->cp_alias_dev); + cp->cp_alias_dev = NULL; + } + g_free(physpath); + } +} + struct g_provider * g_dev_getprovider(struct cdev *dev) { @@ -107,7 +150,6 @@ g_dev_getprovider(struct cdev *dev) return (cp->provider); } - static struct g_geom * g_dev_taste(struct g_class *mp, struct g_provider *pp, int insist __unused) { @@ -167,6 +209,9 @@ g_dev_taste(struct g_class *mp, struct g_provider *pp, int insist __unused) adev->si_drv1 = gp; adev->si_drv2 = cp; } + + g_dev_attrchanged(cp, "GEOM::physpath"); + return (gp); } @@ -365,6 +410,11 @@ g_dev_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread case DIOCGSTRIPEOFFSET: *(off_t *)data = cp->provider->stripeoffset; break; + case DIOCGPHYSPATH: + error = g_io_getattr("GEOM::physpath", cp, &i, data); + if (error == 0 && *(char *)data == '\0') + error = ENOENT; + break; default: if (cp->provider->geom->ioctl != NULL) { error = cp->provider->geom->ioctl(cp->provider, cmd, data, fflag, td); diff --git a/sys/geom/geom_disk.c b/sys/geom/geom_disk.c index e663e3dd29e..17cae6828f9 100644 --- a/sys/geom/geom_disk.c +++ b/sys/geom/geom_disk.c @@ -347,6 +347,15 @@ g_disk_start(struct bio *bp) } while (bp2 != NULL); break; case BIO_GETATTR: + /* Give the driver a chance to override */ + if (dp->d_getattr != NULL) { + if (bp->bio_disk == NULL) + bp->bio_disk = dp; + error = dp->d_getattr(bp); + if (error != -1) + break; + error = EJUSTRETURN; + } if (g_handleattr_int(bp, "GEOM::candelete", (dp->d_flags & DISKFLAG_CANDELETE) != 0)) break; @@ -582,6 +591,18 @@ disk_gone(struct disk *dp) g_wither_provider(pp, ENXIO); } +void +disk_attr_changed(struct disk *dp, const char *attr, int flag) +{ + struct g_geom *gp; + struct g_provider *pp; + + gp = dp->d_geom; + if (gp != NULL) + LIST_FOREACH(pp, &gp->provider, provider) + (void)g_attr_changed(pp, attr, flag); +} + static void g_kern_disks(void *p, int flag __unused) { diff --git a/sys/geom/geom_disk.h b/sys/geom/geom_disk.h index 2d5f15d7cd3..e92f4aa5cc7 100644 --- a/sys/geom/geom_disk.h +++ b/sys/geom/geom_disk.h @@ -49,6 +49,7 @@ struct disk; typedef int disk_open_t(struct disk *); typedef int disk_close_t(struct disk *); typedef void disk_strategy_t(struct bio *bp); +typedef int disk_getattr_t(struct bio *bp); typedef int disk_ioctl_t(struct disk *, u_long cmd, void *data, int fflag, struct thread *td); /* NB: disk_ioctl_t SHALL be cast'able to d_ioctl_t */ @@ -75,6 +76,7 @@ struct disk { disk_strategy_t *d_strategy; disk_ioctl_t *d_ioctl; dumper_t *d_dump; + disk_getattr_t *d_getattr; /* Info fields from driver to geom_disk.c. Valid when open */ u_int d_sectorsize; @@ -104,6 +106,7 @@ struct disk *disk_alloc(void); void disk_create(struct disk *disk, int version); void disk_destroy(struct disk *disk); void disk_gone(struct disk *disk); +void disk_attr_changed(struct disk *dp, const char *attr, int flag); #define DISK_VERSION_00 0x58561059 #define DISK_VERSION_01 0x5856105a diff --git a/sys/geom/geom_event.c b/sys/geom/geom_event.c index d6e54981eab..1e2fc8d2715 100644 --- a/sys/geom/geom_event.c +++ b/sys/geom/geom_event.c @@ -110,6 +110,53 @@ g_waitidlelock(void) } #endif +struct g_attrchanged_args { + struct g_provider *pp; + const char *attr; +}; + +static void +g_attr_changed_event(void *arg, int flag) +{ + struct g_attrchanged_args *args; + struct g_provider *pp; + struct g_consumer *cp; + struct g_consumer *next_cp; + + args = arg; + pp = args->pp; + + g_topology_assert(); + if (flag != EV_CANCEL && g_shutdown == 0) { + + /* + * Tell all consumers of the change. + */ + LIST_FOREACH_SAFE(cp, &pp->consumers, consumers, next_cp) { + if (cp->geom->attrchanged != NULL) + cp->geom->attrchanged(cp, args->attr); + } + } + g_free(args); +} + +int +g_attr_changed(struct g_provider *pp, const char *attr, int flag) +{ + struct g_attrchanged_args *args; + int error; + + args = g_malloc(sizeof *args, flag); + if (args == NULL) + return (ENOMEM); + args->pp = pp; + args->attr = attr; + error = g_post_event(g_attr_changed_event, args, flag, pp, NULL); + if (error != 0) + g_free(args); + return (error); +} + void g_orphan_provider(struct g_provider *pp, int error) { diff --git a/sys/geom/geom_subr.c b/sys/geom/geom_subr.c index a0958f30da0..6e2589b023f 100644 --- a/sys/geom/geom_subr.c +++ b/sys/geom/geom_subr.c @@ -350,6 +350,7 @@ g_new_geomf(struct g_class *mp, const char *fmt, ...) /* Fill in defaults from class */ gp->start = mp->start; gp->spoiled = mp->spoiled; + gp->attrchanged = mp->attrchanged; gp->dumpconf = mp->dumpconf; gp->access = mp->access; gp->orphan = mp->orphan; diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC index ca82b9dded6..c4548c6bce1 100644 --- a/sys/i386/conf/GENERIC +++ b/sys/i386/conf/GENERIC @@ -308,6 +308,7 @@ options USB_DEBUG # enable debug msgs device uhci # UHCI PCI->USB interface device ohci # OHCI PCI->USB interface device ehci # EHCI PCI->USB interface (USB 2.0) +device xhci # XHCI PCI->USB interface (USB 3.0) device usb # USB Bus (required) #device udbp # USB Double Bulk Pipe devices (needs netgraph) device uhid # "Human Interface Devices" diff --git a/sys/kern/kern_conf.c b/sys/kern/kern_conf.c index 59b876c18e5..a4d90c78218 100644 --- a/sys/kern/kern_conf.c +++ b/sys/kern/kern_conf.c @@ -963,6 +963,68 @@ make_dev_alias_p(int flags, struct cdev **cdev, struct cdev *pdev, return (res); } +int +make_dev_physpath_alias(int flags, struct cdev **cdev, struct cdev *pdev, + struct cdev *old_alias, const char *physpath) +{ + char *devfspath; + int physpath_len; + int max_parentpath_len; + int parentpath_len; + int devfspathbuf_len; + int mflags; + int ret; + + *cdev = NULL; + devfspath = NULL; + physpath_len = strlen(physpath); + ret = EINVAL; + if (physpath_len == 0) + goto out; + + if (strncmp("id1,", physpath, 4) == 0) { + physpath += 4; + physpath_len -= 4; + if (physpath_len == 0) + goto out; + } + + max_parentpath_len = SPECNAMELEN - physpath_len - /*/*/1; + parentpath_len = strlen(pdev->si_name); + if (max_parentpath_len < parentpath_len) { + printf("make_dev_physpath_alias: WARNING - Unable to alias %s " + "to %s/%s - path too long\n", + pdev->si_name, physpath, pdev->si_name); + ret = ENAMETOOLONG; + goto out; + } + + mflags = (flags & MAKEDEV_NOWAIT) ? M_NOWAIT : M_WAITOK; + devfspathbuf_len = physpath_len + /*/*/1 + parentpath_len + /*NUL*/1; + devfspath = malloc(devfspathbuf_len, M_DEVBUF, mflags); + if (devfspath == NULL) { + ret = ENOMEM; + goto out; + } + + sprintf(devfspath, "%s/%s", physpath, pdev->si_name); + if (old_alias != NULL + && strcmp(old_alias->si_name, devfspath) == 0) { + /* Retain the existing alias. */ + *cdev = old_alias; + old_alias = NULL; + ret = 0; + } else { + ret = make_dev_alias_p(flags, cdev, pdev, devfspath); + } +out: + if (old_alias != NULL) + destroy_dev(old_alias); + if (devfspath != NULL) + free(devfspath, M_DEVBUF); + return (ret); +} + static void destroy_devl(struct cdev *dev) { diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 6510e13a487..bb25d17977f 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -701,8 +701,9 @@ proc_reap(struct thread *td, struct proc *p, int *status, int options, */ if (p->p_oppid && (t = pfind(p->p_oppid)) != NULL) { PROC_LOCK(p); - p->p_oppid = 0; proc_reparent(p, t); + p->p_pptr->p_dbg_child--; + p->p_oppid = 0; PROC_UNLOCK(p); pksignal(t, SIGCHLD, p->p_ksi); wakeup(t); @@ -794,7 +795,8 @@ kern_wait(struct thread *td, pid_t pid, int *status, int options, pid = -q->p_pgid; PROC_UNLOCK(q); } - if (options &~ (WUNTRACED|WNOHANG|WCONTINUED|WNOWAIT|WLINUXCLONE)) + /* If we don't know the option, just return. */ + if (options & ~(WUNTRACED|WNOHANG|WCONTINUED|WNOWAIT|WLINUXCLONE)) return (EINVAL); loop: if (q->p_flag & P_STATCHILD) { @@ -873,7 +875,10 @@ loop: } if (nfound == 0) { sx_xunlock(&proctree_lock); - return (ECHILD); + if (td->td_proc->p_dbg_child) + return (0); + else + return (ECHILD); } if (options & WNOHANG) { sx_xunlock(&proctree_lock); diff --git a/sys/kern/subr_devstat.c b/sys/kern/subr_devstat.c index 24963d56959..eaf6427e962 100644 --- a/sys/kern/subr_devstat.c +++ b/sys/kern/subr_devstat.c @@ -49,8 +49,9 @@ static long devstat_generation = 1; static int devstat_version = DEVSTAT_VERSION; static int devstat_current_devnumber; static struct mtx devstat_mutex; +MTX_SYSINIT(devstat_mutex, &devstat_mutex, "devstat", MTX_DEF); -static struct devstatlist device_statq; +static struct devstatlist device_statq = STAILQ_HEAD_INITIALIZER(device_statq); static struct devstat *devstat_alloc(void); static void devstat_free(struct devstat *); static void devstat_add_entry(struct devstat *ds, const void *dev_name, @@ -70,13 +71,7 @@ devstat_new_entry(const void *dev_name, devstat_priority priority) { struct devstat *ds; - static int once; - if (!once) { - STAILQ_INIT(&device_statq); - mtx_init(&devstat_mutex, "devstat", NULL, MTX_DEF); - once = 1; - } mtx_assert(&devstat_mutex, MA_NOTOWNED); ds = devstat_alloc(); @@ -476,8 +471,9 @@ devstat_alloc(void) mtx_assert(&devstat_mutex, MA_NOTOWNED); if (!once) { - make_dev_credf(MAKEDEV_ETERNAL, &devstat_cdevsw, 0, NULL, - UID_ROOT, GID_WHEEL, 0400, DEVSTAT_DEVICE_NAME); + make_dev_credf(MAKEDEV_ETERNAL | MAKEDEV_CHECKNAME, + &devstat_cdevsw, 0, NULL, UID_ROOT, GID_WHEEL, 0400, + DEVSTAT_DEVICE_NAME); once = 1; } spp2 = NULL; diff --git a/sys/kern/subr_kdb.c b/sys/kern/subr_kdb.c index a56a56a3a9e..3b1838cba43 100644 --- a/sys/kern/subr_kdb.c +++ b/sys/kern/subr_kdb.c @@ -247,29 +247,44 @@ kdb_reboot(void) #define KEY_CRTLP 16 /* ^P */ #define KEY_CRTLR 18 /* ^R */ +/* States of th KDB "alternate break sequence" detecting state machine. */ +enum { + KDB_ALT_BREAK_SEEN_NONE, + KDB_ALT_BREAK_SEEN_CR, + KDB_ALT_BREAK_SEEN_CR_TILDE, +}; + int kdb_alt_break(int key, int *state) { int brk; + /* All states transition to KDB_ALT_BREAK_SEEN_CR on a CR. */ + if (key == KEY_CR) { + *state = KDB_ALT_BREAK_SEEN_CR; + return (0); + } + brk = 0; switch (*state) { - case 0: - if (key == KEY_CR) - *state = 1; - break; - case 1: + case KDB_ALT_BREAK_SEEN_CR: + *state = KDB_ALT_BREAK_SEEN_NONE; if (key == KEY_TILDE) - *state = 2; + *state = KDB_ALT_BREAK_SEEN_CR_TILDE; break; - case 2: + case KDB_ALT_BREAK_SEEN_CR_TILDE: + *state = KDB_ALT_BREAK_SEEN_NONE; if (key == KEY_CRTLB) brk = KDB_REQ_DEBUGGER; else if (key == KEY_CRTLP) brk = KDB_REQ_PANIC; else if (key == KEY_CRTLR) brk = KDB_REQ_REBOOT; - *state = 0; + break; + case KDB_ALT_BREAK_SEEN_NONE: + default: + *state = KDB_ALT_BREAK_SEEN_NONE; + break; } return (brk); } diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c index a7f280a0410..a4c0069bcf8 100644 --- a/sys/kern/sys_process.c +++ b/sys/kern/sys_process.c @@ -831,8 +831,11 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data) /* security check done above */ p->p_flag |= P_TRACED; p->p_oppid = p->p_pptr->p_pid; - if (p->p_pptr != td->td_proc) + if (p->p_pptr != td->td_proc) { + /* Remember that a child is being debugged(traced). */ + p->p_pptr->p_dbg_child++; proc_reparent(p, td->td_proc); + } data = SIGSTOP; goto sendsig; /* in PT_CONTINUE below */ @@ -919,11 +922,12 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data) PROC_UNLOCK(pp); PROC_LOCK(p); proc_reparent(p, pp); + p->p_pptr->p_dbg_child--; if (pp == initproc) p->p_sigparent = SIGCHLD; } - p->p_flag &= ~(P_TRACED | P_WAITED | P_FOLLOWFORK); p->p_oppid = 0; + p->p_flag &= ~(P_TRACED | P_WAITED | P_FOLLOWFORK); /* should we send SIGCHLD? */ /* childproc_continued(p); */ diff --git a/sys/net/if.h b/sys/net/if.h index d291da85fe5..06521cbd928 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -199,6 +199,13 @@ struct if_data { * field. IFCAP_* and CSUM_* do not match one to one and CSUM_* may be * more detailed or differenciated than IFCAP_*. * Hwassist features are defined CSUM_* in sys/mbuf.h + * + * Capabilities that cannot be arbitrarily changed with ifconfig/ioctl + * are listed in IFCAP_CANTCHANGE, similar to IFF_CANTCHANGE. + * This is not strictly necessary because the common code never + * changes capabilities, and it is left to the individual driver + * to do the right thing. However, having the filter here + * avoids replication of the same code in all individual drivers. */ #define IFCAP_RXCSUM 0x00001 /* can offload checksum on RX */ #define IFCAP_TXCSUM 0x00002 /* can offload checksum on TX */ @@ -220,12 +227,15 @@ struct if_data { #define IFCAP_POLLING_NOCOUNT 0x20000 /* polling ticks cannot be fragmented */ #define IFCAP_VLAN_HWTSO 0x40000 /* can do IFCAP_TSO on VLANs */ #define IFCAP_LINKSTATE 0x80000 /* the runtime link state is dynamic */ +#define IFCAP_NETMAP 0x100000 /* netmap mode supported/enabled */ #define IFCAP_HWCSUM (IFCAP_RXCSUM | IFCAP_TXCSUM) #define IFCAP_TSO (IFCAP_TSO4 | IFCAP_TSO6) #define IFCAP_WOL (IFCAP_WOL_UCAST | IFCAP_WOL_MCAST | IFCAP_WOL_MAGIC) #define IFCAP_TOE (IFCAP_TOE4 | IFCAP_TOE6) +#define IFCAP_CANTCHANGE (IFCAP_NETMAP) + #define IFQ_MAXLEN 50 #define IFNET_SLOWHZ 1 /* granularity is 1 second */ diff --git a/sys/netinet/ipfw/ip_fw2.c b/sys/netinet/ipfw/ip_fw2.c index 49c48b9ad03..9e5c7377953 100644 --- a/sys/netinet/ipfw/ip_fw2.c +++ b/sys/netinet/ipfw/ip_fw2.c @@ -84,6 +84,7 @@ __FBSDID("$FreeBSD$"); #include #include #ifdef INET6 +#include #include #include #endif @@ -646,21 +647,27 @@ send_reject(struct ip_fw_args *args, int code, int iplen, struct ip *ip) * we tried and failed, or any other value if successful. */ static int -check_uidgid(ipfw_insn_u32 *insn, int proto, struct ifnet *oif, - struct in_addr dst_ip, u_int16_t dst_port, struct in_addr src_ip, - u_int16_t src_port, int *ugid_lookupp, - struct ucred **uc, struct inpcb *inp) +check_uidgid(ipfw_insn_u32 *insn, struct ip_fw_args *args, int *ugid_lookupp, + struct ucred **uc) { #ifndef __FreeBSD__ + /* XXX */ return cred_check(insn, proto, oif, dst_ip, dst_port, src_ip, src_port, (struct bsd_ucred *)uc, ugid_lookupp, ((struct mbuf *)inp)->m_skb); #else /* FreeBSD */ + struct in_addr src_ip, dst_ip; struct inpcbinfo *pi; + struct ipfw_flow_id *id; + struct inpcb *pcb, *inp; + struct ifnet *oif; int lookupflags; - struct inpcb *pcb; int match; + id = &args->f_id; + inp = args->inp; + oif = args->oif; + /* * Check to see if the UDP or TCP stack supplied us with * the PCB. If so, rather then holding a lock and looking @@ -681,10 +688,10 @@ check_uidgid(ipfw_insn_u32 *insn, int proto, struct ifnet *oif, */ if (*ugid_lookupp == -1) return (0); - if (proto == IPPROTO_TCP) { + if (id->proto == IPPROTO_TCP) { lookupflags = 0; pi = &V_tcbinfo; - } else if (proto == IPPROTO_UDP) { + } else if (id->proto == IPPROTO_UDP) { lookupflags = INPLOOKUP_WILDCARD; pi = &V_udbinfo; } else @@ -692,19 +699,36 @@ check_uidgid(ipfw_insn_u32 *insn, int proto, struct ifnet *oif, lookupflags |= INPLOOKUP_RLOCKPCB; match = 0; if (*ugid_lookupp == 0) { - /* - * XXXRW: If we had the mbuf here, could use - * in_pcblookup_mbuf(). - */ - pcb = (oif) ? - in_pcblookup(pi, - dst_ip, htons(dst_port), - src_ip, htons(src_port), - lookupflags, oif) : - in_pcblookup(pi, - src_ip, htons(src_port), - dst_ip, htons(dst_port), - lookupflags, NULL); + if (id->addr_type == 6) { +#ifdef INET6 + if (oif == NULL) + pcb = in6_pcblookup_mbuf(pi, + &id->src_ip6, htons(id->src_port), + &id->dst_ip6, htons(id->dst_port), + lookupflags, oif, args->m); + else + pcb = in6_pcblookup_mbuf(pi, + &id->dst_ip6, htons(id->dst_port), + &id->src_ip6, htons(id->src_port), + lookupflags, oif, args->m); +#else + *ugid_lookupp = -1; + return (0); +#endif + } else { + src_ip.s_addr = htonl(id->src_ip); + dst_ip.s_addr = htonl(id->dst_ip); + if (oif == NULL) + pcb = in_pcblookup_mbuf(pi, + src_ip, htons(id->src_port), + dst_ip, htons(id->dst_port), + lookupflags, oif, args->m); + else + pcb = in_pcblookup_mbuf(pi, + dst_ip, htons(id->dst_port), + src_ip, htons(id->src_port), + lookupflags, oif, args->m); + } if (pcb != NULL) { INP_RLOCK_ASSERT(pcb); *uc = crhold(pcb->inp_cred); @@ -719,14 +743,14 @@ check_uidgid(ipfw_insn_u32 *insn, int proto, struct ifnet *oif, *ugid_lookupp = -1; return (0); } - } + } if (insn->o.opcode == O_UID) match = ((*uc)->cr_uid == (uid_t)insn->d[0]); else if (insn->o.opcode == O_GID) match = groupmember((gid_t)insn->d[0], *uc); else if (insn->o.opcode == O_JAIL) match = ((*uc)->cr_prison->pr_id == (int)insn->d[0]); - return match; + return (match); #endif /* __FreeBSD__ */ } @@ -1264,22 +1288,17 @@ do { \ * as this ensures that we have a * packet with the ports info. */ - if (offset!=0) - break; - if (is_ipv6) /* XXX to be fixed later */ + if (offset != 0) break; if (proto == IPPROTO_TCP || proto == IPPROTO_UDP) match = check_uidgid( (ipfw_insn_u32 *)cmd, - proto, oif, - dst_ip, dst_port, - src_ip, src_port, &ucred_lookup, + args, &ucred_lookup, #ifdef __FreeBSD__ - &ucred_cache, args->inp); + &ucred_cache); #else - (void *)&ucred_cache, - (struct inpcb *)args->m); + (void *)&ucred_cache); #endif break; @@ -1394,18 +1413,15 @@ do { \ else if (v == 4 || v == 5) { check_uidgid( (ipfw_insn_u32 *)cmd, - proto, oif, - dst_ip, dst_port, - src_ip, src_port, &ucred_lookup, + args, &ucred_lookup, #ifdef __FreeBSD__ - &ucred_cache, args->inp); + &ucred_cache); if (v == 4 /* O_UID */) key = ucred_cache->cr_uid; else if (v == 5 /* O_JAIL */) key = ucred_cache->cr_prison->pr_id; #else /* !__FreeBSD__ */ - (void *)&ucred_cache, - (struct inpcb *)args->m); + (void *)&ucred_cache); if (v ==4 /* O_UID */) key = ucred_cache.uid; else if (v == 5 /* O_JAIL */) @@ -2178,6 +2194,13 @@ do { \ int nat_id; set_match(args, f_pos, chain); + /* Check if this is 'global' nat rule */ + if (cmd->arg1 == 0) { + retval = ipfw_nat_ptr(args, NULL, m); + l = 0; + done = 1; + break; + } t = ((ipfw_insn_nat *)cmd)->nat; if (t == NULL) { nat_id = (cmd->arg1 == IP_FW_TABLEARG) ? diff --git a/sys/netinet/ipfw/ip_fw_nat.c b/sys/netinet/ipfw/ip_fw_nat.c index fd6f09afdf8..1679a97674a 100644 --- a/sys/netinet/ipfw/ip_fw_nat.c +++ b/sys/netinet/ipfw/ip_fw_nat.c @@ -207,7 +207,8 @@ ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m) struct mbuf *mcl; struct ip *ip; /* XXX - libalias duct tape */ - int ldt, retval; + int ldt, retval, found; + struct ip_fw_chain *chain; char *c; ldt = 0; @@ -256,12 +257,44 @@ ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m) ldt = 1; c = mtod(mcl, char *); - if (args->oif == NULL) - retval = LibAliasIn(t->lib, c, - mcl->m_len + M_TRAILINGSPACE(mcl)); - else - retval = LibAliasOut(t->lib, c, - mcl->m_len + M_TRAILINGSPACE(mcl)); + + /* Check if this is 'global' instance */ + if (t == NULL) { + if (args->oif == NULL) { + /* Wrong direction, skip processing */ + args->m = mcl; + return (IP_FW_NAT); + } + + found = 0; + chain = &V_layer3_chain; + IPFW_RLOCK(chain); + /* Check every nat entry... */ + LIST_FOREACH(t, &chain->nat, _next) { + if ((t->mode & PKT_ALIAS_SKIP_GLOBAL) != 0) + continue; + retval = LibAliasOutTry(t->lib, c, + mcl->m_len + M_TRAILINGSPACE(mcl), 0); + if (retval == PKT_ALIAS_OK) { + /* Nat instance recognises state */ + found = 1; + break; + } + } + IPFW_RUNLOCK(chain); + if (found != 1) { + /* No instance found, return ignore */ + args->m = mcl; + return (IP_FW_NAT); + } + } else { + if (args->oif == NULL) + retval = LibAliasIn(t->lib, c, + mcl->m_len + M_TRAILINGSPACE(mcl)); + else + retval = LibAliasOut(t->lib, c, + mcl->m_len + M_TRAILINGSPACE(mcl)); + } /* * We drop packet when: @@ -274,7 +307,7 @@ ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m) if (retval == PKT_ALIAS_ERROR || (args->oif == NULL && (retval == PKT_ALIAS_UNRESOLVED_FRAGMENT || (retval == PKT_ALIAS_IGNORED && - (t->lib->packetAliasMode & PKT_ALIAS_DENY_INCOMING) != 0)))) { + (t->mode & PKT_ALIAS_DENY_INCOMING) != 0)))) { /* XXX - should i add some logging? */ m_free(mcl); args->m = NULL; diff --git a/sys/netinet/libalias/alias.h b/sys/netinet/libalias/alias.h index 2aed8293c13..b12b353a0fd 100644 --- a/sys/netinet/libalias/alias.h +++ b/sys/netinet/libalias/alias.h @@ -197,17 +197,6 @@ struct mbuf *m_megapullup(struct mbuf *, int); */ #define PKT_ALIAS_RESET_ON_ADDR_CHANGE 0x20 -#ifndef NO_FW_PUNCH -/* - * If PKT_ALIAS_PUNCH_FW is set, active FTP and IRC DCC connections will - * create a 'hole' in the firewall to allow the transfers to work. The - * ipfw rule number that the hole is created with is controlled by - * PacketAliasSetFWBase(). The hole will be attached to that - * particular alias_link, so when the link goes away the hole is deleted. - */ -#define PKT_ALIAS_PUNCH_FW 0x100 -#endif - /* * If PKT_ALIAS_PROXY_ONLY is set, then NAT will be disabled and only * transparent proxying is performed. @@ -220,6 +209,23 @@ struct mbuf *m_megapullup(struct mbuf *, int); */ #define PKT_ALIAS_REVERSE 0x80 +#ifndef NO_FW_PUNCH +/* + * If PKT_ALIAS_PUNCH_FW is set, active FTP and IRC DCC connections will + * create a 'hole' in the firewall to allow the transfers to work. The + * ipfw rule number that the hole is created with is controlled by + * PacketAliasSetFWBase(). The hole will be attached to that + * particular alias_link, so when the link goes away the hole is deleted. + */ +#define PKT_ALIAS_PUNCH_FW 0x100 +#endif + +/* + * If PKT_ALIAS_SKIP_GLOBAL is set, nat instance is not checked for matching + * states in 'ipfw nat global' rule. + */ +#define PKT_ALIAS_SKIP_GLOBAL 0x200 + /* Function return codes. */ #define PKT_ALIAS_ERROR -1 #define PKT_ALIAS_OK 1 diff --git a/sys/sys/conf.h b/sys/sys/conf.h index 0c7ed41c3c4..08e158267f2 100644 --- a/sys/sys/conf.h +++ b/sys/sys/conf.h @@ -280,6 +280,9 @@ struct cdev *make_dev_alias(struct cdev *_pdev, const char *_fmt, ...) __printflike(2, 3); int make_dev_alias_p(int _flags, struct cdev **_cdev, struct cdev *_pdev, const char *_fmt, ...) __printflike(4, 5); +int make_dev_physpath_alias(int _flags, struct cdev **_cdev, + struct cdev *_pdev, struct cdev *_old_alias, + const char *_physpath); void dev_lock(void); void dev_unlock(void); void setconf(void); diff --git a/sys/sys/disk.h b/sys/sys/disk.h index ba25c89bfa8..112eed0747b 100644 --- a/sys/sys/disk.h +++ b/sys/sys/disk.h @@ -116,4 +116,12 @@ void disk_err(struct bio *bp, const char *what, int blkdone, int nl); * This should be a multiple of the sector size. */ +#define DIOCGPHYSPATH _IOR('d', 141, char[MAXPATHLEN]) + /* + * Get a string defining the physical path for a given provider. + * This has similar rules to ident, but is intended to uniquely + * identify the physical location of the device, not the current + * occupant of that location. + */ + #endif /* _SYS_DISK_H_ */ diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 4d7b540c2e6..c54a95699e2 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -503,6 +503,8 @@ struct proc { /* The following fields are all zeroed upon creation in fork. */ #define p_startzero p_oppid pid_t p_oppid; /* (c + e) Save ppid in ptrace. XXX */ + int p_dbg_child; /* (c + e) # of debugged children in + ptrace. */ struct vmspace *p_vmspace; /* (b) Address space. */ u_int p_swtick; /* (c) Tick when swapped in or out. */ struct itimerval p_realtimer; /* (c) Alarm timer. */ diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index 1197f489d70..6730daed3c9 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -10417,6 +10417,10 @@ softdep_disk_write_complete(bp) WORKLIST_INSERT(&reattach, wk); continue; + case D_FREEDEP: + free_freedep(WK_FREEDEP(wk)); + continue; + default: panic("handle_disk_write_complete: Unknown type %s", TYPENAME(wk->wk_type)); diff --git a/usr.sbin/diskinfo/diskinfo.c b/usr.sbin/diskinfo/diskinfo.c index 2f00936df0b..168a9098262 100644 --- a/usr.sbin/diskinfo/diskinfo.c +++ b/usr.sbin/diskinfo/diskinfo.c @@ -39,6 +39,7 @@ #include #include #include +#include #include static void @@ -57,7 +58,7 @@ int main(int argc, char **argv) { int i, ch, fd, error, exitval = 0; - char buf[BUFSIZ], ident[DISK_IDENT_SIZE]; + char buf[BUFSIZ], ident[DISK_IDENT_SIZE], physpath[MAXPATHLEN]; off_t mediasize, stripesize, stripeoffset; u_int sectorsize, fwsectors, fwheads; @@ -151,6 +152,8 @@ main(int argc, char **argv) } if (ioctl(fd, DIOCGIDENT, ident) == 0) printf("\t%-12s\t# Disk ident.\n", ident); + if (ioctl(fd, DIOCGPHYSPATH, physpath) == 0) + printf("\t%-12s\t# Physical path\n", physpath); } printf("\n"); if (opt_c)