diff --git a/usr/src/cmd/captoinfo/captoinfo.c b/usr/src/cmd/captoinfo/captoinfo.c index fc26e626d6b0..3a7fc5b3e81f 100644 --- a/usr/src/cmd/captoinfo/captoinfo.c +++ b/usr/src/cmd/captoinfo/captoinfo.c @@ -27,8 +27,6 @@ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * NAME * captoinfo - convert a termcap description to a terminfo description @@ -229,7 +227,7 @@ checktermcap() "%s: TERM=%s: wrong type given for the " "boolean termcap code '%.2s'.\n", progname, term_name, tbuf); - continue; + continue; } /* look for the name in nums */ @@ -239,7 +237,7 @@ checktermcap() "%s: TERM=%s: wrong type given for the " "numeric termcap code '%.2s'.\n", progname, term_name, tbuf); - continue; + continue; } /* look for the name in strs */ @@ -249,7 +247,7 @@ checktermcap() "%s: TERM=%s: wrong type given for the " "string termcap code '%.2s'.\n", progname, term_name, tbuf); - continue; + continue; } (void) fprintf(stderr, @@ -469,7 +467,7 @@ search(char *names[], int max, char *infoname) for (i = 0; names [i] != NULL; i++) if (strcmp(names [i], infoname) == 0) return (i); - return (-1); + return (-1); #else /* this doesn't work for some reason */ char **bret; @@ -1037,7 +1035,7 @@ fancycap(char *string) } string++; } - return (0); + return (0); } /* @@ -1367,7 +1365,7 @@ initdirname(void) #endif /* SYSV || USG */ if (verbose) (void) fprintf(trace, "current directory name=%s.\n", dirname); - environ = newenviron; + environ = newenviron; } static void diff --git a/usr/src/cmd/zonecfg/zonecfg.c b/usr/src/cmd/zonecfg/zonecfg.c index ab3586069107..f6aa8678d471 100644 --- a/usr/src/cmd/zonecfg/zonecfg.c +++ b/usr/src/cmd/zonecfg/zonecfg.c @@ -416,6 +416,7 @@ static const char *net_res_scope_cmds[] = { "help", "info", "set address=", + "set allowed-address=", "set physical=", "set defrouter=", NULL diff --git a/usr/src/common/ficl/emu/loader_emu.c b/usr/src/common/ficl/emu/loader_emu.c index 67b631cf4d00..d109016176a3 100644 --- a/usr/src/common/ficl/emu/loader_emu.c +++ b/usr/src/common/ficl/emu/loader_emu.c @@ -1146,6 +1146,7 @@ command_help(int argc, char *argv[]) switch (argc) { case 3: subtopic = strdup(argv[2]); + /* FALLTHROUGH */ case 2: topic = strdup(argv[1]); break; diff --git a/usr/src/common/ficl/float.c b/usr/src/common/ficl/float.c index 3442259f59e9..02f64b8c9b54 100644 --- a/usr/src/common/ficl/float.c +++ b/usr/src/common/ficl/float.c @@ -294,7 +294,7 @@ ficlVmParseFloatNumber(ficlVm *vm, ficlString s) if (c == '+') { break; } - /* Note! Drop through to FPS_ININT */ + /* FALLTHROUGH */ /* * Converting integer part of number. * Only allow digits, decimal and 'E'. @@ -339,7 +339,7 @@ ficlVmParseFloatNumber(ficlVm *vm, ficlString s) } else if (c == '+') { break; } - /* Note! Drop through to FPS_INEXP */ + /* FALLTHROUGH */ /* * Processing the exponent part of number. * Only allow digits. diff --git a/usr/src/common/ficl/primitives.c b/usr/src/common/ficl/primitives.c index c8b982970571..63ec19c377b2 100644 --- a/usr/src/common/ficl/primitives.c +++ b/usr/src/common/ficl/primitives.c @@ -417,9 +417,11 @@ ficlPrimitiveSprintf(ficlVm *vm) case 'x': case 'X': base = 16; + /* FALLTHROUGH */ case 'u': case 'U': unsignedInteger = 1; /* true */ + /* FALLTHROUGH */ case 'd': case 'D': { int integer; @@ -437,6 +439,7 @@ ficlPrimitiveSprintf(ficlVm *vm) case '%': source = format; actualLength = 1; + /* FALLTHROUGH */ default: continue; } diff --git a/usr/src/common/ficl/vm.c b/usr/src/common/ficl/vm.c index a284008deb77..1917d3fd90bd 100644 --- a/usr/src/common/ficl/vm.c +++ b/usr/src/common/ficl/vm.c @@ -147,6 +147,7 @@ ficlVmOptimizeJumpToJump(ficlVm *vm, ficlIp ip) case ficlInstructionBranchParenWithCheck: /* preoptimize where we're jumping to */ ficlVmOptimizeJumpToJump(vm, destination); + /* FALLTHROUGH */ case ficlInstructionBranchParen: destination++; destination += *(ficlInteger *)destination; diff --git a/usr/src/lib/libcurses/screen/termcap.ed b/usr/src/lib/libcurses/screen/termcap.ed index da5735809150..6375be8dfb13 100644 --- a/usr/src/lib/libcurses/screen/termcap.ed +++ b/usr/src/lib/libcurses/screen/termcap.ed @@ -16,8 +16,6 @@ H * contributors. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Simulation of termcap using terminfo. * This file is created from termcap.ed. DO NOT EDIT ME! @@ -60,17 +58,18 @@ _stripdelays(char *inbuf, char *outbuf, int size) if (inbuf == NULL) return (0); - else - while (size && *inbuf) - if (*inbuf == '$' && *(inbuf+1) == '<') - /* LINTED */ - while (*inbuf && *inbuf++ != '>'); - else { - size--; - *outbuf++ = *inbuf++; - *outbuf = 0; - } - return (saveoutbuf); + + while (size && *inbuf) { + if (*inbuf == '$' && *(inbuf+1) == '<') { + /* LINTED */ + while (*inbuf && *inbuf++ != '>'); + } else { + size--; + *outbuf++ = *inbuf++; + *outbuf = 0; + } + } + return (saveoutbuf); } /* generated by sort on caps */ diff --git a/usr/src/lib/libcurses/screen/tparm.c b/usr/src/lib/libcurses/screen/tparm.c index 99d03d532699..49f2d3852da2 100644 --- a/usr/src/lib/libcurses/screen/tparm.c +++ b/usr/src/lib/libcurses/screen/tparm.c @@ -135,7 +135,8 @@ pop(STACK *st) return (st->stack[st->top--]); } -/* The following routine was added to make lint shut up about converting from +/* + * The following routine was added to make lint shut up about converting from * a long to a char *. It is identical to the pop routine, except for the * cast on the return statement. */ @@ -165,16 +166,16 @@ free_stack(STACK *st) } -char * +char * tparm_p0(char *instring) { long p[] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; return (tparm(instring, p[0], p[1], p[2], p[3], p[4], p[5], p[6], - p[7], p[8])); + p[7], p[8])); } -char * +char * tparm_p1(char *instring, long l1) { long p[] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -182,10 +183,10 @@ tparm_p1(char *instring, long l1) p[0] = l1; return (tparm(instring, p[0], p[1], p[2], p[3], p[4], p[5], p[6], - p[7], p[8])); + p[7], p[8])); } -char * +char * tparm_p2(char *instring, long l1, long l2) { long p[] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -194,10 +195,10 @@ tparm_p2(char *instring, long l1, long l2) p[1] = l2; return (tparm(instring, p[0], p[1], p[2], p[3], p[4], p[5], p[6], - p[7], p[8])); + p[7], p[8])); } -char * +char * tparm_p3(char *instring, long l1, long l2, long l3) { long p[] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -207,10 +208,10 @@ tparm_p3(char *instring, long l1, long l2, long l3) p[2] = l3; return (tparm(instring, p[0], p[1], p[2], p[3], p[4], p[5], p[6], - p[7], p[8])); + p[7], p[8])); } -char * +char * tparm_p4(char *instring, long l1, long l2, long l3, long l4) { long p[] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -221,12 +222,12 @@ tparm_p4(char *instring, long l1, long l2, long l3, long l4) p[3] = l4; return (tparm(instring, p[0], p[1], p[2], p[3], p[4], p[5], p[6], - p[7], p[8])); + p[7], p[8])); } -char * +char * tparm_p7(char *instring, long l1, long l2, long l3, long l4, long l5, long l6, - long l7) + long l7) { long p[] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -239,13 +240,13 @@ tparm_p7(char *instring, long l1, long l2, long l3, long l4, long l5, long l6, p[6] = l7; return (tparm(instring, p[0], p[1], p[2], p[3], p[4], p[5], p[6], - p[7], p[8])); + p[7], p[8])); } /* VARARGS */ -char * +char * tparm(char *instring, long fp1, long fp2, long p3, long p4, - long p5, long p6, long p7, long p8, long p9) + long p5, long p6, long p7, long p8, long p9) { static char result[512]; static char added[100]; @@ -257,7 +258,7 @@ tparm(char *instring, long fp1, long fp2, long p3, long p4, long op; long op2; int sign; - int onrow = 0; + volatile int onrow = 0; volatile long p1 = fp1, p2 = fp2; /* copy in case < 2 actual parms */ char *xp; char formatbuffer[100]; @@ -386,8 +387,7 @@ tparm(char *instring, long fp1, long fp2, long p3, long p4, * now. */ if (c == 's') - (void) sprintf(outp, formatbuffer, - (char *) op); + (void) sprintf(outp, formatbuffer, (char *)op); else (void) sprintf(outp, formatbuffer, op); /* @@ -398,7 +398,7 @@ tparm(char *instring, long fp1, long fp2, long p3, long p4, * BSD emulations are particularly confusing. */ while (*outp) - outp++; + outp++; (void) pop(&stk); continue; @@ -425,24 +425,24 @@ tparm(char *instring, long fp1, long fp2, long p3, long p4, */ switch (op) { /* - * Null. Problem is that our - * output is, by convention, null terminated. - */ + * Null. Problem is that our + * output is, by convention, null terminated. + */ case 0: op = 0200; /* Parity should */ /* be ignored. */ break; /* - * Control D. Problem is that certain very - * ancient hardware hangs up on this, so the - * current(!) UNIX tty driver doesn't xmit - * control D's. - */ + * Control D. Problem is that certain very + * ancient hardware hangs up on this, so the + * current(!) UNIX tty driver doesn't xmit + * control D's. + */ case _CHCTRL('d'): /* - * Newline. Problem is that UNIX will expand - * this to CRLF. - */ + * Newline. Problem is that UNIX will expand + * this to CRLF. + */ case '\n': xp = (onrow ? cursor_down : cursor_right); @@ -486,10 +486,10 @@ tparm(char *instring, long fp1, long fp2, long p3, long p4, break; /* - * %i: shorthand for increment first two parms. - * Useful for terminals that start numbering from - * one instead of zero(like ANSI terminals). - */ + * %i: shorthand for increment first two parms. + * Useful for terminals that start numbering from + * one instead of zero(like ANSI terminals). + */ case 'i': p1++; p2++; @@ -545,8 +545,8 @@ tparm(char *instring, long fp1, long fp2, long p3, long p4, } else { if (*cp >= 'A' && *cp <= 'Z') { regs[*cp++ - 'A'] = - /* LINTED */ - (short) pop(&stk); + /* LINTED */ + (short)pop(&stk); } #ifdef DEBUG else if (outf) { @@ -692,17 +692,17 @@ tparm(char *instring, long fp1, long fp2, long p3, long p4, /* Sorry, no unary minus, because minus is binary. */ /* - * If-then-else. Implemented by a low level hack of - * skipping forward until the match is found, counting - * nested if-then-elses. - */ + * If-then-else. Implemented by a low level hack of + * skipping forward until the match is found, counting + * nested if-then-elses. + */ case '?': /* IF - just a marker */ break; case 't': /* THEN - branch if false */ if (!pop(&stk)) cp = _branchto(cp, 'e'); - break; + break; case 'e': /* ELSE - branch to ENDIF */ cp = _branchto(cp, ';'); diff --git a/usr/src/lib/libcurses/screen/waddch.c b/usr/src/lib/libcurses/screen/waddch.c index 31c7627981fe..91cfa65c4264 100644 --- a/usr/src/lib/libcurses/screen/waddch.c +++ b/usr/src/lib/libcurses/screen/waddch.c @@ -37,8 +37,6 @@ * contributors. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /*LINTLIBRARY*/ #include @@ -100,12 +98,13 @@ waddch(WINDOW *win, chtype c) chtype space = ' ' | rawattrs; if ((newx = x + (TABSIZE - - (x % TABSIZE))) > win->_maxx) + (x % TABSIZE))) > win->_maxx) { newx = win->_maxx; - for (; x < newx; x++) - if (waddch(win, - space) == ERR) - goto next; + } + for (; x < newx; x++) { + if (waddch(win, space) == ERR) + goto next; + } } else { if ((waddch(win, (chtype) '^'|rawattrs) == ERR) || @@ -173,18 +172,22 @@ next : } #endif /* DEBUG */ break; - } else + } else { savimmed = 1; - } else + } + } else { y++; - x = 0; - } else + } + x = 0; + } else { savimmed += 2; + } #ifdef FULLDEBUG - if (outf) + if (outf) { fprintf(outf, "ADDCH: 2: y = %d, x = %d, " "firstch = %d, lastch = %d\n", y, x, win->_firstch[y], win->_lastch[y]); + } #endif /* FULLDEBUG */ break; } diff --git a/usr/src/lib/libcurses/screen/wnoutref.c b/usr/src/lib/libcurses/screen/wnoutref.c index 3f9dd35054fa..8f1e7050c884 100644 --- a/usr/src/lib/libcurses/screen/wnoutref.c +++ b/usr/src/lib/libcurses/screen/wnoutref.c @@ -37,8 +37,6 @@ * contributors. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /*LINTLIBRARY*/ #include @@ -53,8 +51,8 @@ wnoutrefresh(WINDOW *win) short *bch, *ech, *sbch, *sech; chtype **wcp, **scp, *wc, *sc; int *hash; - short y, x, xorg, yorg, scrli, scrco, - boty, sminy, smaxy, minx, maxx, lo, hi; + short y, x, xorg, yorg, scrli, scrco, boty, sminy, smaxy, minx, + maxx, lo, hi; bool doall; if (win->_parent) @@ -138,13 +136,13 @@ wnoutrefresh(WINDOW *win) for (x = lo - 1; x >= minx; --x) if (!ISCBIT(wc[x])) break; - if (x < minx) { - for (x = lo+1; x <= maxx; ++x) - if (!ISCBIT(wc[x])) - break; - if (x > maxx) - goto nextline; - } + if (x < minx) { + for (x = lo + 1; x <= maxx; ++x) + if (!ISCBIT(wc[x])) + break; + if (x > maxx) + goto nextline; + } lo = x; } if (ISMBIT(wc[hi])) { @@ -188,7 +186,7 @@ wnoutrefresh(WINDOW *win) /* update the image */ wc = *wcp + lo; sc = *scp + lo + xorg; - (void) memcpy((char *) sc, (char *) wc, (size_t) + (void) memcpy((char *)sc, (char *)wc, (size_t) (((hi - lo) + 1) * sizeof (chtype))); /* the hash value of the line */ diff --git a/usr/src/lib/libcurses/screen/wrefresh.c b/usr/src/lib/libcurses/screen/wrefresh.c index 41a589fbe8bc..7b704c6d29dd 100644 --- a/usr/src/lib/libcurses/screen/wrefresh.c +++ b/usr/src/lib/libcurses/screen/wrefresh.c @@ -37,8 +37,6 @@ * contributors. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /*LINTLIBRARY*/ #include @@ -146,14 +144,14 @@ wrefresh(WINDOW *win) * If there is no exit_attribute mode, then vidupdate * could only possibly turn off one of the below three * so that's all we ask it turn off. - */ + */ vidupdate(A_NORMAL, (A_ALTCHARSET | A_STANDOUT | A_UNDERLINE), _outch); SP->fl_endwin = FALSE; #ifdef _VR2_COMPAT_CODE - _endwin = (char) FALSE; + _endwin = (char)FALSE; #endif /* _VR2_COMPAT_CODE */ } @@ -218,7 +216,7 @@ wrefresh(WINDOW *win) /* there is type-ahead */ if (!curwin && (_INPUTPENDING = _chkinput()) == TRUE) { /* LINTED */ - _VIRTTOP = (short) wy; + _VIRTTOP = (short)wy; goto done; } @@ -263,9 +261,9 @@ wrefresh(WINDOW *win) if (wy != cy || wx != cx) { (void) mvcur(cy, cx, wy, wx); /* LINTED */ - cy = (short) wy; + cy = (short)wy; /* LINTED */ - cx = (short) wx; + cx = (short)wx; } /* reset the flags */ @@ -298,8 +296,7 @@ _shove(int wy) /* allocate space for shifted line */ if (length < scrco) { - if (line) - free((char *) line); + free(line); line = (chtype *) malloc(scrco * sizeof (chtype)); length = line ? scrco : 0; } @@ -371,7 +368,7 @@ _updateln(int wy) { chtype *wcp, *scp, *wp, *sp, wc, sc; int wx, lastx, x, mtch, idch, blnkx, idcx, video_attrx, - color_attrx, maxi, endns, begns, wx_sav, multi_col; + color_attrx, maxi, endns, begns, wx_sav, multi_col; bool redraw, changed, didcolor, didvideo; redraw = (_virtscr->_firstch[wy] == _REDRAW); @@ -565,12 +562,12 @@ _updateln(int wy) _PUTS(clr_bol, 1); /* LINTED */ - cy = (short) wy; + cy = (short)wy; /* LINTED */ - cx = (short) x; + cx = (short)x; mtch = x - wx; - (void) memcpy((char *) scp, (char *) wcp, + (void) memcpy(scp, wcp, (mtch * sizeof (chtype))); wcp += mtch; scp += mtch; @@ -585,9 +582,9 @@ _updateln(int wy) if (cy != wy || cx != wx) (void) mvcur(cy, cx, wy, wx); /* LINTED */ - cy = (short) wy; + cy = (short)wy; /* LINTED */ - cx = (short) wx; + cx = (short)wx; /* update screen image */ while (wx < lastx) { @@ -609,9 +606,9 @@ _updateln(int wy) _PUTS(clr_eol, 1); /* LINTED */ - curscr->_curx = (short) wx; - /* LINTED */ - curscr->_cury = (short) wy; + curscr->_curx = (short)wx; + /* LINTED */ + curscr->_cury = (short)wy; (void) wclrtoeol(curscr); if (marks && wx > 0 && _ATTR(*(scp - 1)) != @@ -643,15 +640,21 @@ _updateln(int wy) /* color and video attributes */ if (_ATTR(wc) != curscr->_attrs) { - bool color_change = FALSE; - bool video_change = FALSE; - - if (marks) - if (_VIDEO(wc) != _VIDEO(curscr->_attrs)) - video_change = TRUE; - if (color_marks) - if (_COLOR(wc) != _COLOR(curscr->_attrs)) - color_change = TRUE; + bool color_change = FALSE; + bool video_change = FALSE; + + if (marks) { + if (_VIDEO(wc) != + _VIDEO(curscr->_attrs)) { + video_change = TRUE; + } + } + if (color_marks) { + if (_COLOR(wc) != + _COLOR(curscr->_attrs)) { + color_change = TRUE; + } + } /* the following may occurs when, for */ /* example the application */ @@ -694,8 +697,8 @@ _updateln(int wy) color_attrx); /* * sc = _COLOR(curscr->_y[wy][color_attrx]); - *_VIDS(sc, (~sc & A_COLOR)); - */ + * _VIDS(sc, (~sc & A_COLOR)); + */ _VIDS(_COLOR(_virtscr->_y[wy] [color_attrx]), _COLOR(_virtscr->_y[wy] @@ -762,7 +765,7 @@ _updateln(int wy) if (_DARKCHAR(*scp)) break; /* LINTED */ - _BEGNS[wy] = (short) wx; + _BEGNS[wy] = (short)wx; if (wx == scrco) _ENDNS[wy] = -1; else { @@ -772,7 +775,7 @@ _updateln(int wy) if (_DARKCHAR(*scp)) break; /* LINTED */ - _ENDNS[wy] = (short) wx; + _ENDNS[wy] = (short)wx; } /* update the hash structure */ @@ -925,7 +928,7 @@ _useidch(chtype *wcp, chtype *scp, int length, int maxi, int *id) /* update the screen image */ for (x1 = length - 1, x2 = length - idch - 1; x2 >= 0; --x1, --x2) scp[x1] = scp[x2]; - (void) memcpy((char *) scp, (char *) wcp, idch * sizeof (chtype)); + (void) memcpy(scp, wcp, idch * sizeof (chtype)); *id = idch; return (match + idch); @@ -1096,7 +1099,7 @@ _rmargin(int wx) /* update screen image */ /* LINTED */ - cx = (short) wx; + cx = (short)wx; curscr->_y[cy][wx] = wcp[wx]; for (x = wx + 1; x < scrco; ++x) { (void) _outwch(wcp[x]); @@ -1205,13 +1208,13 @@ _useceod(int topy, int boty) _PUTS(clear_screen, scrli); cy = 0; cx = 0; (void) werase(curscr); - } else + } else { /* use clear-to-end-of-display or delete lines */ if (clr_eos || (parm_delete_line && !memory_below)) { (void) mvcur(cy, cx, topy, 0); /* LINTED */ - cy = (short) topy; + cy = (short)topy; cx = 0; /* SS: colors */ if (back_color_erase) @@ -1221,15 +1224,17 @@ _useceod(int topy, int boty) /* update curscr */ /* LINTED */ - curscr->_cury = (short) topy; + curscr->_cury = (short)topy; curscr->_curx = 0; (void) wclrtobot(curscr); - } else + } else { /* no hardware support */ return; + } + } - /* correct the update structure */ - (void) wtouchln(_virtscr, topy, scrli, FALSE); + /* correct the update structure */ + (void) wtouchln(_virtscr, topy, scrli, FALSE); } diff --git a/usr/src/lib/libmvec/common/__vhypotf.c b/usr/src/lib/libmvec/common/__vhypotf.c index c8215aadfbf3..5fcd7a80c258 100644 --- a/usr/src/lib/libmvec/common/__vhypotf.c +++ b/usr/src/lib/libmvec/common/__vhypotf.c @@ -30,52 +30,57 @@ #include "libm_inlines.h" #ifdef __RESTRICT -#define restrict _Restrict +#define restrict _Restrict #else -#define restrict +#define restrict #endif extern double sqrt(double); +/* + * Instead of type punning, use union type. + */ +typedef union h32 { + float f; + unsigned u; +} h32; + void -__vhypotf(int n, float * restrict x, int stridex, float * restrict y, - int stridey, float * restrict z, int stridez) +__vhypotf(int n, float *restrict x, int stridex, float *restrict y, + int stridey, float *restrict z, int stridez) { float x0, x1, x2, y0, y1, y2, z0, z1, z2, *pz0, *pz1, *pz2; - unsigned hx0, hx1, hx2, hy0, hy1, hy2; - int i, j0, j1, j2; + h32 hx0, hx1, hx2, hy0, hy1, hy2; + int i, j0, j1, j2; - do - { + do { LOOP0: - hx0 = *(unsigned*)x & ~0x80000000; - hy0 = *(unsigned*)y & ~0x80000000; - *(unsigned*)&x0 = hx0; - *(unsigned*)&y0 = hy0; - if (hy0 > hx0) - { - i = hy0 - hx0; - j0 = hy0 & 0x7f800000; - if (hx0 == 0) + hx0.f = *x; + hy0.f = *y; + hx0.u &= ~0x80000000; + hy0.u &= ~0x80000000; + x0 = hx0.f; + y0 = hy0.f; + if (hy0.u > hx0.u) { + i = hy0.u - hx0.u; + j0 = hy0.u & 0x7f800000; + if (hx0.u == 0) i = 0x7f800000; - } - else - { - i = hx0 - hy0; - j0 = hx0 & 0x7f800000; - if (hy0 == 0) + } else { + i = hx0.u - hy0.u; + j0 = hx0.u & 0x7f800000; + if (hy0.u == 0) i = 0x7f800000; - else if (hx0 == 0) + else if (hx0.u == 0) i = 0x7f800000; } - if (i >= 0x0c800000 || j0 >= 0x7f800000) - { + if (i >= 0x0c800000 || j0 >= 0x7f800000) { z0 = x0 + y0; - if (hx0 == 0x7f800000) + if (hx0.u == 0x7f800000) z0 = x0; - else if (hy0 == 0x7f800000) + else if (hy0.u == 0x7f800000) z0 = y0; - else if (hx0 > 0x7f800000 || hy0 > 0x7f800000) + else if (hx0.u > 0x7f800000 || hy0.u > 0x7f800000) z0 = *x + *y; *z = z0; x += stridex; @@ -95,34 +100,32 @@ __vhypotf(int n, float * restrict x, int stridex, float * restrict y, break; LOOP1: - hx1 = *(unsigned*)x & ~0x80000000; - hy1 = *(unsigned*)y & ~0x80000000; - *(unsigned*)&x1 = hx1; - *(unsigned*)&y1 = hy1; - if (hy1 > hx1) - { - i = hy1 - hx1; - j1 = hy1 & 0x7f800000; - if (hx1 == 0) + hx1.f = *x; + hy1.f = *y; + hx1.u &= ~0x80000000; + hy1.u &= ~0x80000000; + x1 = hx1.f; + y1 = hy1.f; + if (hy1.u > hx1.u) { + i = hy1.u - hx1.u; + j1 = hy1.u & 0x7f800000; + if (hx1.u == 0) i = 0x7f800000; - } - else - { - i = hx1 - hy1; - j1 = hx1 & 0x7f800000; - if (hy1 == 0) + } else { + i = hx1.u - hy1.u; + j1 = hx1.u & 0x7f800000; + if (hy1.u == 0) i = 0x7f800000; - else if (hx1 == 0) + else if (hx1.u == 0) i = 0x7f800000; } - if (i >= 0x0c800000 || j1 >= 0x7f800000) - { + if (i >= 0x0c800000 || j1 >= 0x7f800000) { z1 = x1 + y1; - if (hx1 == 0x7f800000) + if (hx1.u == 0x7f800000) z1 = x1; - else if (hy1 == 0x7f800000) + else if (hy1.u == 0x7f800000) z1 = y1; - else if (hx1 > 0x7f800000 || hy1 > 0x7f800000) + else if (hx1.u > 0x7f800000 || hy1.u > 0x7f800000) z1 = *x + *y; *z = z1; x += stridex; @@ -142,34 +145,32 @@ __vhypotf(int n, float * restrict x, int stridex, float * restrict y, break; LOOP2: - hx2 = *(unsigned*)x & ~0x80000000; - hy2 = *(unsigned*)y & ~0x80000000; - *(unsigned*)&x2 = hx2; - *(unsigned*)&y2 = hy2; - if (hy2 > hx2) - { - i = hy2 - hx2; - j2 = hy2 & 0x7f800000; - if (hx2 == 0) + hx2.f = *x; + hy2.f = *y; + hx2.u &= ~0x80000000; + hy2.u &= ~0x80000000; + x2 = hx2.f; + y2 = hy2.f; + if (hy2.u > hx2.u) { + i = hy2.u - hx2.u; + j2 = hy2.u & 0x7f800000; + if (hx2.u == 0) i = 0x7f800000; - } - else - { - i = hx2 - hy2; - j2 = hx2 & 0x7f800000; - if (hy2 == 0) + } else { + i = hx2.u - hy2.u; + j2 = hx2.u & 0x7f800000; + if (hy2.u == 0) i = 0x7f800000; - else if (hx2 == 0) + else if (hx2.u == 0) i = 0x7f800000; } - if (i >= 0x0c800000 || j2 >= 0x7f800000) - { + if (i >= 0x0c800000 || j2 >= 0x7f800000) { z2 = x2 + y2; - if (hx2 == 0x7f800000) + if (hx2.u == 0x7f800000) z2 = x2; - else if (hy2 == 0x7f800000) + else if (hy2.u == 0x7f800000) z2 = y2; - else if (hx2 > 0x7f800000 || hy2 > 0x7f800000) + else if (hx2.u > 0x7f800000 || hy2.u > 0x7f800000) z2 = *x + *y; *z = z2; x += stridex; @@ -195,10 +196,8 @@ __vhypotf(int n, float * restrict x, int stridex, float * restrict y, i = 0; } while (--n > 0); - if (i > 0) - { - if (i > 1) - { + if (i > 0) { + if (i > 1) { z1 = sqrt(x1 * (double)x1 + y1 * (double)y1); *pz1 = z1; } diff --git a/usr/src/lib/libshell/common/sh/lex.c b/usr/src/lib/libshell/common/sh/lex.c index 5a2f7c239f62..b6fbbc1779e7 100644 --- a/usr/src/lib/libshell/common/sh/lex.c +++ b/usr/src/lib/libshell/common/sh/lex.c @@ -1082,11 +1082,13 @@ int sh_lex(Lex_t* lp) } /* backward compatibility */ { + char *tmp; if(lp->lexd.warn) errormsg(SH_DICT,ERROR_warn(0),e_lexnested,shp->inlineno); if(!(state=lp->lexd.first)) state = fcfirst(); - fcseek(state-fcseek(0)); + tmp = fcseek(0); + fcseek(state - tmp); if(lp->arg) { lp->arg = (struct argnod*)stkfreeze(stkp,1); diff --git a/usr/src/pkg/manifests/system-test-ostest.mf b/usr/src/pkg/manifests/system-test-ostest.mf index 38b5c23533be..ee0d19c66305 100644 --- a/usr/src/pkg/manifests/system-test-ostest.mf +++ b/usr/src/pkg/manifests/system-test-ostest.mf @@ -12,7 +12,7 @@ # # Copyright (c) 2012, 2016 by Delphix. All rights reserved. # Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved. -# Copyright 2016, Joyent, Inc. +# Copyright 2017 Joyent, Inc. # set name=pkg.fmri value=pkg:/system/test/ostest@$(PKGVERS) @@ -26,6 +26,7 @@ dir path=opt/os-tests/bin dir path=opt/os-tests/runfiles dir path=opt/os-tests/tests dir path=opt/os-tests/tests/file-locking +dir path=opt/os-tests/tests/pf_key dir path=opt/os-tests/tests/sdevfs dir path=opt/os-tests/tests/secflags dir path=opt/os-tests/tests/sigqueue @@ -39,6 +40,9 @@ file path=opt/os-tests/tests/file-locking/acquire-lock.32 mode=0555 file path=opt/os-tests/tests/file-locking/acquire-lock.64 mode=0555 file path=opt/os-tests/tests/file-locking/runtests.32 mode=0555 file path=opt/os-tests/tests/file-locking/runtests.64 mode=0555 +file path=opt/os-tests/tests/pf_key/acquire-compare mode=0555 +file path=opt/os-tests/tests/pf_key/acquire-spray mode=0555 +file path=opt/os-tests/tests/pf_key/eacq-enabler mode=0555 file path=opt/os-tests/tests/poll_test mode=0555 file path=opt/os-tests/tests/sdevfs/sdevfs_eisdir mode=0555 file path=opt/os-tests/tests/secflags/addrs-32 mode=0555 @@ -66,4 +70,5 @@ file path=opt/os-tests/tests/spoof-ras mode=0555 file path=opt/os-tests/tests/stress/dladm-kstat mode=0555 license cr_Sun license=cr_Sun license lic_CDDL license=lic_CDDL +depend fmri=pkg:/network/telnet type=require depend fmri=system/test/testrunner type=require diff --git a/usr/src/test/os-tests/runfiles/default.run b/usr/src/test/os-tests/runfiles/default.run index bff7ec6baa17..d029b75e7bc4 100644 --- a/usr/src/test/os-tests/runfiles/default.run +++ b/usr/src/test/os-tests/runfiles/default.run @@ -11,7 +11,7 @@ # # Copyright (c) 2012 by Delphix. All rights reserved. -# Copyright 2016 Joyent, Inc. +# Copyright 2017 Joyent, Inc. # [DEFAULT] @@ -58,3 +58,7 @@ tests = ['runtests.32', 'runtests.64'] [/opt/os-tests/tests/sockfs] user = root tests = ['conn', 'dgram', 'drop_priv', 'nosignal', 'sockpair'] + +[/opt/os-tests/tests/pf_key] +user = root +tests = ['acquire-compare', 'acquire-spray'] diff --git a/usr/src/test/os-tests/tests/Makefile b/usr/src/test/os-tests/tests/Makefile index 77af4061209f..f3af454450e5 100644 --- a/usr/src/test/os-tests/tests/Makefile +++ b/usr/src/test/os-tests/tests/Makefile @@ -11,8 +11,10 @@ # # Copyright (c) 2012, 2016 by Delphix. All rights reserved. +# Copyright 2017 Joyent, Inc. # -SUBDIRS = poll secflags sigqueue spoof-ras sdevfs sockfs stress file-locking +SUBDIRS = poll secflags sigqueue spoof-ras sdevfs sockfs stress file-locking \ + pf_key include $(SRC)/test/Makefile.com diff --git a/usr/src/test/os-tests/tests/pf_key/Makefile b/usr/src/test/os-tests/tests/pf_key/Makefile new file mode 100644 index 000000000000..e35d0028528c --- /dev/null +++ b/usr/src/test/os-tests/tests/pf_key/Makefile @@ -0,0 +1,55 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2017 Joyent, Inc. +# + +include $(SRC)/cmd/Makefile.cmd +include $(SRC)/test/Makefile.com + +# Shell scripts... +PROG = acquire-spray \ + acquire-compare + +PROG += eacq-enabler + +ROOTOPTPKG = $(ROOT)/opt/os-tests +TESTDIR = $(ROOTOPTPKG)/tests/pf_key + +CMDS = $(PROG:%=$(TESTDIR)/%) +$(CMDS) := FILEMODE = 0555 + +LDLIBS += -lsocket + +eacq-enabler: + $(LINK.c) eacq-enabler.c -o $@ $(LDLIBS) + $(POST_PROCESS) + +all: $(PROG) + +install: all $(CMDS) + +lint: + +clobber: clean + -$(RM) $(PROG) + +clean: + -$(RM) $(CLEANFILES) + +$(CMDS): $(TESTDIR) $(PROG) + +$(TESTDIR): + $(INS.dir) + +$(TESTDIR)/%: % + $(INS.file) diff --git a/usr/src/test/os-tests/tests/pf_key/acquire-compare.sh b/usr/src/test/os-tests/tests/pf_key/acquire-compare.sh new file mode 100644 index 000000000000..b35a377540ad --- /dev/null +++ b/usr/src/test/os-tests/tests/pf_key/acquire-compare.sh @@ -0,0 +1,170 @@ +#!/usr/bin/ksh + +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2017 Joyent, Inc. +# + +if [ `id -u` -ne 0 ]; then + echo "Need to be root or have effective UID of root." + exit 255 +fi + +# NOTE: If multihomed, this may fail in interesting ways... +MY_IP=`netstat -in -f inet | egrep -v "Name|lo0" | awk '{print $4}' | head -1` +TEST_REMOTE_DST1=10.90.1.25 +TEST_REMOTE_DST2=10.19.84.2 +TEST_REMOTE_DST3=10.19.84.3 +TEST_REMOTE_DST4=10.19.84.4 + +T1_SRC=10.21.12.4 +T1_DST=10.21.12.5 +T1_PREFIX=10.21.12.0/24 +T2_SRC=10.51.50.4 +T2_DST=10.51.50.5 +T2_PREFIX=10.51.50.0/24 + +MONITOR_LOG=/tmp/ipseckey-monitor.$$ + +EACQ_PROG=/opt/os-tests/tests/pf_key/eacq-enabler + +$EACQ_PROG & +eapid=$! + +echo "Warning, this trashes IPsec policy." +ipsecconf -Fq + +# Setup the IPsec policy... +ipsecconf -qa - << EOF +# Global policy... +# Remote-port-based policy. Use different algorithms... +{ raddr $TEST_REMOTE_DST3 rport 23 ulp tcp } ipsec { encr_algs aes encr_auth_algs sha512 } + +# Unique policy... +{ raddr $TEST_REMOTE_DST4 rport 23 ulp tcp } ipsec { encr_algs aes encr_auth_algs sha256 sa unique } + +# Simple IP address policy. Use an AH + ESP for it. +{ raddr $TEST_REMOTE_DST1 } ipsec { auth_algs sha512 encr_algs aes(256) } +{ raddr $TEST_REMOTE_DST2 } ipsec { auth_algs sha384 encr_algs aes(256) } + +# Tunnel policy... +{ tunnel rush0 raddr $T1_PREFIX negotiate tunnel } ipsec { encr_algs aes-gcm(256) } +# NULL-encryption... +{ tunnel vh0 raddr $T2_PREFIX negotiate tunnel } ipsec {encr_auth_algs hmac-sha384 } +EOF + +# Plumb the tunnels +dladm create-iptun -t -T ipv4 -a local=$MY_IP -a remote=$TEST_REMOTE_DST1 rush0 +dladm create-iptun -t -T ipv4 -a local=$MY_IP -a remote=$TEST_REMOTE_DST2 vh0 +ipadm create-addr -t -T static -a local=$T1_SRC,remote=$T1_DST rush0/v4 +ipadm create-addr -t -T static -a local=$T2_SRC,remote=$T2_DST vh0/v4 +route add $T1_PREFIX $T1_DST +route add $T2_PREFIX $T2_DST + +ipseckey flush +ipseckey -np monitor > $MONITOR_LOG & +IPSECKEY_PID=$! + +# Launch pings and telnets to different addresses (each requiring an ACQUIRE). +ping -svn $TEST_REMOTE_DST1 1024 1 2>&1 > /dev/null & +p1=$! +ping -svn $TEST_REMOTE_DST2 1024 1 2>&1 > /dev/null & +p2=$! +ping -svn $T1_DST 1024 1 2>&1 > /dev/null & +p3=$! +ping -svn $T2_DST 1024 1 2>&1 > /dev/null & +p4=$! + +echo "Waiting for pings..." +pwait $p1 $p2 $p3 $p4 + +# Now try some telnets to trigger port and unique policy. +# port-only for DST3 +telnet $TEST_REMOTE_DST3 & +tpid=$! +t1port=`pfiles $tpid | grep sockname | awk '{print $5}'` +echo "First local port == $t1port" +sleep 10 ; kill $tpid +# unique for DST4 +telnet $TEST_REMOTE_DST4 & +tpid=$! +t2port=`pfiles $tpid | grep sockname | awk '{print $5}'` +echo "Second local port == $t2port" +sleep 10 ; kill $tpid +# Nothing specced for DST1 +telnet $TEST_REMOTE_DST1 & +tpid=$! +t3port=`pfiles $tpid | grep sockname | awk '{print $5}'` +echo "Third local port == $t3port" +sleep 10 ; kill $tpid + +# Clean up. +kill $IPSECKEY_PID +kill $eapid +# Unplumb the tunnels +route delete $T2_PREFIX $T2_DST +route delete $T1_PREFIX $T1_DST +ipadm delete-addr vh0/v4 +ipadm delete-addr rush0/v4 +ipadm delete-if vh0 +ipadm delete-if rush0 +dladm delete-iptun vh0 +dladm delete-iptun rush0 +# Flush policy +ipsecconf -Fq +# Use SMF to restore anything that may have been there. "restart" on +# a disabled service is a NOP, but an enabled one will get +# /etc/inet/ipsecinit.conf reloaded. +svcadm restart ipsec/policy + +# Process MONITOR_LOG's output... +echo "Checking for unique local port only in one ACQUIRE case." +egrep "$t1port|$t2port|$t3port" $MONITOR_LOG > /tmp/egrep.$$ +grep $t2port $MONITOR_LOG > /tmp/grep.$$ +diff /tmp/grep.$$ /tmp/egrep.$$ +if [[ $? != 0 ]]; then + echo "More than just the one unique port, $tport2, found in monitor output." + /bin/rm -f /tmp/grep.$$ /tmp/egrep.$$ $MONITOR_LOG + exit 1 +fi + +# Split out extended (file.0) and regular (file.1) ACQUIREs. +# NOTE: "+7" is dependent on "ipseckey monitor"'s first output where it gets +# the "PROMISC" reply. + +mkdir /tmp/raw.$$ +savedir=$PWD +cd /tmp/raw.$$ +tail +7 $MONITOR_LOG | \ + awk 'BEGIN { out=0; } /Read/ {out++;} { print >> (out % 2) }' +cd $savedir + +# Pluck out the address extension from the two ACQUIRE types. +# NOTE: Add any new in-ACQUIRE address types here if more arrive. +egrep "DST:|SRC:|INS:|IND:" /tmp/raw.$$/0 > /tmp/extended-addresses.$$ +egrep "DST:|SRC:|INS:|IND:" /tmp/raw.$$/1 > /tmp/regular-addresses.$$ + +# There should be NO differences between address fields from regular vs. +# extended ACQUIREs. If there are, it's a bug (or an older version of illumos). +diff /tmp/extended-addresses.$$ /tmp/regular-addresses.$$ +if [[ $? != 0 ]]; then + echo "Address fields in ACQUIRE differ." + rc=1 +else + rc=0 +fi + +/bin/rm -rf /tmp/*-addresses.$$ /tmp/raw.$$ +/bin/rm -f /tmp/grep.$$ /tmp/egrep.$$ /tmp/addrs.$$ $MONITOR_LOG + +exit $rc diff --git a/usr/src/test/os-tests/tests/pf_key/acquire-spray.sh b/usr/src/test/os-tests/tests/pf_key/acquire-spray.sh new file mode 100644 index 000000000000..d15c8617a69c --- /dev/null +++ b/usr/src/test/os-tests/tests/pf_key/acquire-spray.sh @@ -0,0 +1,99 @@ +#!/usr/bin/ksh + +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2017 Joyent, Inc. +# + +if [ `id -u` -ne 0 ]; then + echo "Need to be root or have effective UID of root." + exit 255 +fi + +if [[ `zonename` != "global" ]]; then + echo "Need to be the in the global zone for lock detection." + exit 254 +fi + +# This test sprays many concurrent ACQUIRE messages. The idea originally +# was to view lock contention on the global netstack's IPsec algorithm lock. +# It is also useful for having multiple ACQUIRE records. + +PREFIX=10.21.12.0/24 +MONITOR_LOG=/var/run/ipseckey-monitor.$$ + +# The program that sends an extended REGISTER to enable extended ACQUIREs. +EACQ_PROG=/opt/os-tests/tests/pf_key/eacq-enabler + +$EACQ_PROG & +eapid=$! + +# Find the ipsec_alg_lock to monitor with lockstat (below). +GLOBAL_NETSTACK=`echo ::netstack | mdb -k | grep -w 0 | awk '{print $1}'` +GLOBAL_IPSEC=`echo $GLOBAL_NETSTACK::print netstack_t | mdb -k | grep -w nu_ipsec | awk '{print $3}'` +IPSEC_ALG_LOCK=`echo $GLOBAL_IPSEC::print -a ipsec_stack_t ipsec_alg_lock | mdb -k | head -1 | awk '{print $1}'` + +#echo "WARNING -- this test flushes out IPsec policy..." +#echo "GLOBAL_NETSTACK = $GLOBAL_NETSTACK" +#echo "GLOBAL_IPSEC = $GLOBAL_IPSEC" +#echo "IPSEC_ALG_LOCK = $IPSEC_ALG_LOCK" + +# Tunnels will be preserved by using -f instead of -F. +ipsecconf -qf + +# Simple one-type-of-ESP setup... +echo "{ raddr $PREFIX } ipsec { encr_algs aes encr_auth_algs sha512 }" | \ + ipsecconf -qa - +# ipsecconf -ln + +# Get monitoring PF_KEY for at least regular ACQUIREs. +ipseckey -n monitor > $MONITOR_LOG & +IPSECKEY_PID=$! + +# Flush out the SADB to make damned sure we don't have straggler acquire +# records internally. +ipseckey flush + +# Launch 254 pings to different addresses (each requiring an ACQUIRE). +i=1 +while [ $i -le 254 ]; do + truss -Topen -o /dev/null ping -svn 10.21.12.$i 1024 1 2>&1 > /dev/null & + i=$(($i + 1)) +done + +# Unleash the pings in 10 seconds, Smithers. +( sleep 10 ; prun `pgrep ping` ) & + +# Get the lockstats going now. +echo "Running: lockstat -A -l 0x$IPSEC_ALG_LOCK,8 sleep 30" +lockstat -A -l 0x$IPSEC_ALG_LOCK,8 sleep 30 +kill $IPSECKEY_PID +kill $eapid +# Use SMF to restore anything that may have been there. "restart" on +# a disabled service is a NOP, but an enabled one will get +# /etc/inet/ipsecinit.conf reloaded. +svcadm restart ipsec/policy + +# See if we have decent results. + +numacq=`grep ACQUIRE $MONITOR_LOG | wc -l | awk '{print $1}` +#rm -f $MONITOR_LOG +# Pardon the hardcoding again. +if [[ $numacq != 508 ]]; then + echo "Got $numacq ACQUIREs instead of 508" + exit 1 +else + echo "Saw expected $numacq ACQUIREs." +fi + +exit 0 diff --git a/usr/src/test/os-tests/tests/pf_key/eacq-enabler.c b/usr/src/test/os-tests/tests/pf_key/eacq-enabler.c new file mode 100644 index 000000000000..fcd46fbb3396 --- /dev/null +++ b/usr/src/test/os-tests/tests/pf_key/eacq-enabler.c @@ -0,0 +1,111 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2017 Joyent, Inc. + */ + +/* + * Designed to be backgrounded and just killed. Open a PF_KEY socket, do + * an extended-REGISTER so the kernel will send extended-ACQUIRE messages, + * and then read-and-discard everything off the socket. + */ + +#include +#include +#include +#include +#include +#include + +/* ARGSUSED */ +int +main(int argc, char *argv[]) +{ + int s, rc; + uint64_t buf[1024]; /* PF_KEY likes 64-bit alignment. */ + sadb_msg_t *samsg; + sadb_x_ereg_t *ereg; + boolean_t ah_ack, esp_ack; + pid_t pid = getpid(); + + s = socket(PF_KEY, SOCK_RAW, PF_KEY_V2); + if (s == -1) + err(-1, "socket(PF_KEY)"); + + /* Base message. */ + samsg = (sadb_msg_t *)buf; + ereg = (sadb_x_ereg_t *)(samsg + 1); + samsg->sadb_msg_version = PF_KEY_V2; + samsg->sadb_msg_type = SADB_REGISTER; + samsg->sadb_msg_errno = 0; + samsg->sadb_msg_satype = SADB_SATYPE_UNSPEC; + samsg->sadb_msg_reserved = 0; + samsg->sadb_msg_seq = 1; + samsg->sadb_msg_pid = pid; + samsg->sadb_msg_len = SADB_8TO64(sizeof (*samsg) + sizeof (*ereg)); + + /* extended REGISTER so we can listen for extended ACQUIREs. */ + ereg->sadb_x_ereg_len = SADB_8TO64(sizeof (*ereg)); + ereg->sadb_x_ereg_exttype = SADB_X_EXT_EREG; + ereg->sadb_x_ereg_satypes[0] = SADB_SATYPE_ESP; + ereg->sadb_x_ereg_satypes[1] = SADB_SATYPE_AH; + ereg->sadb_x_ereg_satypes[2] = SADB_SATYPE_UNSPEC; + + rc = write(s, buf, sizeof (*samsg) + sizeof (*ereg)); + if (rc == -1) + err(-1, "Extended register write error"); + + /* + * Extended REGISTER expects a regular REGISTER reply for EACH protocol + * requested. In our case, AH and ESP. + */ + do { + + do { + rc = read(s, buf, sizeof (buf)); + if (rc == -1) + err(-1, "Extended register read error"); + + } while (samsg->sadb_msg_seq != 1 || + samsg->sadb_msg_pid != pid || + samsg->sadb_msg_type != SADB_REGISTER); + + if (samsg->sadb_msg_errno != 0) { + if (samsg->sadb_msg_errno == EPROTONOSUPPORT) { + warn("Protocol %d not supported.", + samsg->sadb_msg_satype); + } else { + errno = samsg->sadb_msg_errno; + err(-1, "Extended REGISTER returned"); + } + } + + switch (samsg->sadb_msg_satype) { + case SADB_SATYPE_ESP: + esp_ack = B_TRUE; + break; + case SADB_SATYPE_AH: + ah_ack = B_TRUE; + break; + default: + err(-1, "Bad satype in extended register ACK %d.", + samsg->sadb_msg_satype); + } + } while (!esp_ack || !ah_ack); + + /* Expect this loop to never end. This program ends via signal. */ + do { + rc = read(s, buf, sizeof (buf)); + } while (rc != -1); + + err(-1, "PF_KEY read error"); +} diff --git a/usr/src/uts/common/fs/zfs/dsl_dataset.c b/usr/src/uts/common/fs/zfs/dsl_dataset.c index 81798db2fc49..5706965ffe20 100644 --- a/usr/src/uts/common/fs/zfs/dsl_dataset.c +++ b/usr/src/uts/common/fs/zfs/dsl_dataset.c @@ -1742,10 +1742,10 @@ get_clones_stat(dsl_dataset_t *ds, nvlist_t *nv) fnvlist_add_nvlist(propval, ZPROP_VALUE, val); fnvlist_add_nvlist(nv, zfs_prop_to_name(ZFS_PROP_CLONES), propval); - } else { - nvlist_free(val); - nvlist_free(propval); } + + nvlist_free(val); + nvlist_free(propval); } /* diff --git a/usr/src/uts/common/fs/zfs/lua/lstrlib.c b/usr/src/uts/common/fs/zfs/lua/lstrlib.c index b6279edc4ad8..86d0ff265487 100644 --- a/usr/src/uts/common/fs/zfs/lua/lstrlib.c +++ b/usr/src/uts/common/fs/zfs/lua/lstrlib.c @@ -958,6 +958,7 @@ static int str_format (lua_State *L) { nb = str_sprintf(buff, form, ni); break; } +#if defined(LUA_USE_FLOAT_FORMATS) case 'e': case 'E': case 'f': #if defined(LUA_USE_AFORMAT) case 'a': case 'A': @@ -967,6 +968,7 @@ static int str_format (lua_State *L) { nb = str_sprintf(buff, form, (LUA_FLTFRM_T)luaL_checknumber(L, arg)); break; } +#endif case 'q': { addquoted(L, &b, arg); break; diff --git a/usr/src/uts/common/fs/zfs/spa.c b/usr/src/uts/common/fs/zfs/spa.c index 8e72500722eb..4fa6a6c79a47 100644 --- a/usr/src/uts/common/fs/zfs/spa.c +++ b/usr/src/uts/common/fs/zfs/spa.c @@ -3024,6 +3024,8 @@ spa_load_best(spa_t *spa, spa_load_state_t state, int mosconfig, if (config && (rewind_error || state != SPA_LOAD_RECOVER)) spa_config_set(spa, config); + else + nvlist_free(config); if (state == SPA_LOAD_RECOVER) { ASSERT3P(loadinfo, ==, NULL); diff --git a/usr/src/uts/common/inet/ip/ipsecah.c b/usr/src/uts/common/inet/ip/ipsecah.c index 6b700d034648..b533d7539823 100644 --- a/usr/src/uts/common/inet/ip/ipsecah.c +++ b/usr/src/uts/common/inet/ip/ipsecah.c @@ -96,20 +96,6 @@ static ipsecahparam_t lcl_param_arr[] = { { 0, 0xffffffffU, 0, "ipsecah_default_hard_usetime"}, { 0, 1, 0, "ipsecah_log_unknown_spi"}, }; -#define ipsecah_debug ipsecah_params[0].ipsecah_param_value -#define ipsecah_age_interval ipsecah_params[1].ipsecah_param_value -#define ipsecah_age_int_max ipsecah_params[1].ipsecah_param_max -#define ipsecah_reap_delay ipsecah_params[2].ipsecah_param_value -#define ipsecah_replay_size ipsecah_params[3].ipsecah_param_value -#define ipsecah_acquire_timeout ipsecah_params[4].ipsecah_param_value -#define ipsecah_larval_timeout ipsecah_params[5].ipsecah_param_value -#define ipsecah_default_soft_bytes ipsecah_params[6].ipsecah_param_value -#define ipsecah_default_hard_bytes ipsecah_params[7].ipsecah_param_value -#define ipsecah_default_soft_addtime ipsecah_params[8].ipsecah_param_value -#define ipsecah_default_hard_addtime ipsecah_params[9].ipsecah_param_value -#define ipsecah_default_soft_usetime ipsecah_params[10].ipsecah_param_value -#define ipsecah_default_hard_usetime ipsecah_params[11].ipsecah_param_value -#define ipsecah_log_unknown_spi ipsecah_params[12].ipsecah_param_value #define ah0dbg(a) printf a /* NOTE: != 0 instead of > 0 so lint doesn't complain. */ @@ -149,7 +135,6 @@ static void ah_outbound_finish(mblk_t *, ip_xmit_attr_t *); static int ipsecah_open(queue_t *, dev_t *, int, int, cred_t *); static int ipsecah_close(queue_t *); static void ipsecah_wput(queue_t *, mblk_t *); -static void ah_send_acquire(ipsacq_t *, mblk_t *, netstack_t *); static boolean_t ah_register_out(uint32_t, uint32_t, uint_t, ipsecah_stack_t *, cred_t *); static void *ipsecah_stack_init(netstackid_t stackid, netstack_t *ns); @@ -420,7 +405,6 @@ ipsecah_stack_init(netstackid_t stackid, netstack_t *ns) (void) ah_kstat_init(ahstack, stackid); ahstack->ah_sadb.s_acquire_timeout = &ahstack->ipsecah_acquire_timeout; - ahstack->ah_sadb.s_acqfn = ah_send_acquire; sadbp_init("AH", &ahstack->ah_sadb, SADB_SATYPE_AH, ah_hash_size, ahstack->ipsecah_netstack); @@ -451,7 +435,6 @@ ipsecah_stack_fini(netstackid_t stackid, void *arg) if (ahstack->ah_pfkey_q != NULL) { (void) quntimeout(ahstack->ah_pfkey_q, ahstack->ah_event); } - ahstack->ah_sadb.s_acqfn = NULL; ahstack->ah_sadb.s_acquire_timeout = NULL; sadbp_destroy(&ahstack->ah_sadb, ahstack->ipsecah_netstack); ip_drop_unregister(&ahstack->ah_dropper); @@ -1736,160 +1719,6 @@ ah_age_bytes(ipsa_t *assoc, uint64_t bytes, boolean_t inbound) return (inrc && outrc); } -/* - * Perform the really difficult work of inserting the proposed situation. - * Called while holding the algorithm lock. - */ -static void -ah_insert_prop(sadb_prop_t *prop, ipsacq_t *acqrec, uint_t combs, - netstack_t *ns) -{ - sadb_comb_t *comb = (sadb_comb_t *)(prop + 1); - ipsec_action_t *ap; - ipsec_prot_t *prot; - ipsecah_stack_t *ahstack = ns->netstack_ipsecah; - ipsec_stack_t *ipss = ns->netstack_ipsec; - - ASSERT(RW_READ_HELD(&ipss->ipsec_alg_lock)); - - prop->sadb_prop_exttype = SADB_EXT_PROPOSAL; - prop->sadb_prop_len = SADB_8TO64(sizeof (sadb_prop_t)); - *(uint32_t *)(&prop->sadb_prop_replay) = 0; /* Quick zero-out! */ - - prop->sadb_prop_replay = ahstack->ipsecah_replay_size; - - /* - * Based upon algorithm properties, and what-not, prioritize a - * proposal, based on the ordering of the AH algorithms in the - * alternatives in the policy rule or socket that was placed - * in the acquire record. - */ - - for (ap = acqrec->ipsacq_act; ap != NULL; - ap = ap->ipa_next) { - ipsec_alginfo_t *aalg; - - if ((ap->ipa_act.ipa_type != IPSEC_POLICY_APPLY) || - (!ap->ipa_act.ipa_apply.ipp_use_ah)) - continue; - - prot = &ap->ipa_act.ipa_apply; - - ASSERT(prot->ipp_auth_alg > 0); - - aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH] - [prot->ipp_auth_alg]; - if (aalg == NULL || !ALG_VALID(aalg)) - continue; - - /* XXX check aalg for duplicates??.. */ - - comb->sadb_comb_flags = 0; - comb->sadb_comb_reserved = 0; - comb->sadb_comb_encrypt = 0; - comb->sadb_comb_encrypt_minbits = 0; - comb->sadb_comb_encrypt_maxbits = 0; - - comb->sadb_comb_auth = aalg->alg_id; - comb->sadb_comb_auth_minbits = - MAX(prot->ipp_ah_minbits, aalg->alg_ef_minbits); - comb->sadb_comb_auth_maxbits = - MIN(prot->ipp_ah_maxbits, aalg->alg_ef_maxbits); - - /* - * The following may be based on algorithm - * properties, but in the meantime, we just pick - * some good, sensible numbers. Key mgmt. can - * (and perhaps should) be the place to finalize - * such decisions. - */ - - /* - * No limits on allocations, since we really don't - * support that concept currently. - */ - comb->sadb_comb_soft_allocations = 0; - comb->sadb_comb_hard_allocations = 0; - - /* - * These may want to come from policy rule.. - */ - comb->sadb_comb_soft_bytes = - ahstack->ipsecah_default_soft_bytes; - comb->sadb_comb_hard_bytes = - ahstack->ipsecah_default_hard_bytes; - comb->sadb_comb_soft_addtime = - ahstack->ipsecah_default_soft_addtime; - comb->sadb_comb_hard_addtime = - ahstack->ipsecah_default_hard_addtime; - comb->sadb_comb_soft_usetime = - ahstack->ipsecah_default_soft_usetime; - comb->sadb_comb_hard_usetime = - ahstack->ipsecah_default_hard_usetime; - - prop->sadb_prop_len += SADB_8TO64(sizeof (*comb)); - if (--combs == 0) - return; /* out of space.. */ - comb++; - } -} - -/* - * Prepare and actually send the SADB_ACQUIRE message to PF_KEY. - */ -static void -ah_send_acquire(ipsacq_t *acqrec, mblk_t *extended, netstack_t *ns) -{ - uint_t combs; - sadb_msg_t *samsg; - sadb_prop_t *prop; - mblk_t *pfkeymp, *msgmp; - ipsecah_stack_t *ahstack = ns->netstack_ipsecah; - ipsec_stack_t *ipss = ns->netstack_ipsec; - - AH_BUMP_STAT(ahstack, acquire_requests); - - if (ahstack->ah_pfkey_q == NULL) { - mutex_exit(&acqrec->ipsacq_lock); - return; - } - - /* Set up ACQUIRE. */ - pfkeymp = sadb_setup_acquire(acqrec, SADB_SATYPE_AH, - ns->netstack_ipsec); - if (pfkeymp == NULL) { - ah0dbg(("sadb_setup_acquire failed.\n")); - mutex_exit(&acqrec->ipsacq_lock); - return; - } - ASSERT(RW_READ_HELD(&ipss->ipsec_alg_lock)); - combs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH]; - msgmp = pfkeymp->b_cont; - samsg = (sadb_msg_t *)(msgmp->b_rptr); - - /* Insert proposal here. */ - - prop = (sadb_prop_t *)(((uint64_t *)samsg) + samsg->sadb_msg_len); - ah_insert_prop(prop, acqrec, combs, ns); - samsg->sadb_msg_len += prop->sadb_prop_len; - msgmp->b_wptr += SADB_64TO8(samsg->sadb_msg_len); - - rw_exit(&ipss->ipsec_alg_lock); - - /* - * Must mutex_exit() before sending PF_KEY message up, in - * order to avoid recursive mutex_enter() if there are no registered - * listeners. - * - * Once I've sent the message, I'm cool anyway. - */ - mutex_exit(&acqrec->ipsacq_lock); - if (extended != NULL) { - putnext(ahstack->ah_pfkey_q, extended); - } - putnext(ahstack->ah_pfkey_q, pfkeymp); -} - /* Refactor me */ /* * Handle the SADB_GETSPI message. Create a larval SA. diff --git a/usr/src/uts/common/inet/ip/ipsecesp.c b/usr/src/uts/common/inet/ip/ipsecesp.c index fb5befa432b6..f98207aecdaf 100644 --- a/usr/src/uts/common/inet/ip/ipsecesp.c +++ b/usr/src/uts/common/inet/ip/ipsecesp.c @@ -21,6 +21,8 @@ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2017 Joyent, Inc. */ #include @@ -95,31 +97,6 @@ static ipsecespparam_t lcl_param_arr[] = { { 0, 2, 1, "ipsecesp_padding_check"}, { 0, 600, 20, "ipsecesp_nat_keepalive_interval"}, }; -#define ipsecesp_debug ipsecesp_params[0].ipsecesp_param_value -#define ipsecesp_age_interval ipsecesp_params[1].ipsecesp_param_value -#define ipsecesp_age_int_max ipsecesp_params[1].ipsecesp_param_max -#define ipsecesp_reap_delay ipsecesp_params[2].ipsecesp_param_value -#define ipsecesp_replay_size ipsecesp_params[3].ipsecesp_param_value -#define ipsecesp_acquire_timeout \ - ipsecesp_params[4].ipsecesp_param_value -#define ipsecesp_larval_timeout \ - ipsecesp_params[5].ipsecesp_param_value -#define ipsecesp_default_soft_bytes \ - ipsecesp_params[6].ipsecesp_param_value -#define ipsecesp_default_hard_bytes \ - ipsecesp_params[7].ipsecesp_param_value -#define ipsecesp_default_soft_addtime \ - ipsecesp_params[8].ipsecesp_param_value -#define ipsecesp_default_hard_addtime \ - ipsecesp_params[9].ipsecesp_param_value -#define ipsecesp_default_soft_usetime \ - ipsecesp_params[10].ipsecesp_param_value -#define ipsecesp_default_hard_usetime \ - ipsecesp_params[11].ipsecesp_param_value -#define ipsecesp_log_unknown_spi \ - ipsecesp_params[12].ipsecesp_param_value -#define ipsecesp_padding_check \ - ipsecesp_params[13].ipsecesp_param_value /* For ipsecesp_nat_keepalive_interval, see ipsecesp.h. */ #define esp0dbg(a) printf a @@ -133,7 +110,6 @@ static int ipsecesp_close(queue_t *); static void ipsecesp_wput(queue_t *, mblk_t *); static void *ipsecesp_stack_init(netstackid_t stackid, netstack_t *ns); static void ipsecesp_stack_fini(netstackid_t stackid, void *arg); -static void esp_send_acquire(ipsacq_t *, mblk_t *, netstack_t *); static void esp_prepare_udp(netstack_t *, mblk_t *, ipha_t *); static void esp_outbound_finish(mblk_t *, ip_xmit_attr_t *); @@ -181,52 +157,6 @@ static taskq_t *esp_taskq; * IPPROTO_ESP */ -/* - * Stats. This may eventually become a full-blown SNMP MIB once that spec - * stabilizes. - */ - -typedef struct esp_kstats_s { - kstat_named_t esp_stat_num_aalgs; - kstat_named_t esp_stat_good_auth; - kstat_named_t esp_stat_bad_auth; - kstat_named_t esp_stat_bad_padding; - kstat_named_t esp_stat_replay_failures; - kstat_named_t esp_stat_replay_early_failures; - kstat_named_t esp_stat_keysock_in; - kstat_named_t esp_stat_out_requests; - kstat_named_t esp_stat_acquire_requests; - kstat_named_t esp_stat_bytes_expired; - kstat_named_t esp_stat_out_discards; - kstat_named_t esp_stat_crypto_sync; - kstat_named_t esp_stat_crypto_async; - kstat_named_t esp_stat_crypto_failures; - kstat_named_t esp_stat_num_ealgs; - kstat_named_t esp_stat_bad_decrypt; - kstat_named_t esp_stat_sa_port_renumbers; -} esp_kstats_t; - -/* - * espstack->esp_kstats is equal to espstack->esp_ksp->ks_data if - * kstat_create_netstack for espstack->esp_ksp succeeds, but when it - * fails, it will be NULL. Note this is done for all stack instances, - * so it *could* fail. hence a non-NULL checking is done for - * ESP_BUMP_STAT and ESP_DEBUMP_STAT - */ -#define ESP_BUMP_STAT(espstack, x) \ -do { \ - if (espstack->esp_kstats != NULL) \ - (espstack->esp_kstats->esp_stat_ ## x).value.ui64++; \ -_NOTE(CONSTCOND) \ -} while (0) - -#define ESP_DEBUMP_STAT(espstack, x) \ -do { \ - if (espstack->esp_kstats != NULL) \ - (espstack->esp_kstats->esp_stat_ ## x).value.ui64--; \ -_NOTE(CONSTCOND) \ -} while (0) - static int esp_kstat_update(kstat_t *, int); static boolean_t @@ -503,6 +433,7 @@ ipsecesp_param_register(IDP *ndp, ipsecespparam_t *espp, int cnt) } return (B_TRUE); } + /* * Initialize things for ESP for each stack instance */ @@ -527,7 +458,6 @@ ipsecesp_stack_init(netstackid_t stackid, netstack_t *ns) espstack->esp_sadb.s_acquire_timeout = &espstack->ipsecesp_acquire_timeout; - espstack->esp_sadb.s_acqfn = esp_send_acquire; sadbp_init("ESP", &espstack->esp_sadb, SADB_SATYPE_ESP, esp_hash_size, espstack->ipsecesp_netstack); @@ -558,7 +488,6 @@ ipsecesp_stack_fini(netstackid_t stackid, void *arg) if (espstack->esp_pfkey_q != NULL) { (void) quntimeout(espstack->esp_pfkey_q, espstack->esp_event); } - espstack->esp_sadb.s_acqfn = NULL; espstack->esp_sadb.s_acquire_timeout = NULL; sadbp_destroy(&espstack->esp_sadb, espstack->ipsecesp_netstack); ip_drop_unregister(&espstack->esp_dropper); @@ -1181,179 +1110,6 @@ esp_inbound(mblk_t *data_mp, void *arg, ip_recv_attr_t *ira) (uint8_t *)esph - data_mp->b_rptr)); } -/* - * Perform the really difficult work of inserting the proposed situation. - * Called while holding the algorithm lock. - */ -static void -esp_insert_prop(sadb_prop_t *prop, ipsacq_t *acqrec, uint_t combs, - netstack_t *ns) -{ - sadb_comb_t *comb = (sadb_comb_t *)(prop + 1); - ipsec_action_t *ap; - ipsec_prot_t *prot; - ipsecesp_stack_t *espstack = ns->netstack_ipsecesp; - ipsec_stack_t *ipss = ns->netstack_ipsec; - - ASSERT(RW_READ_HELD(&ipss->ipsec_alg_lock)); - - prop->sadb_prop_exttype = SADB_EXT_PROPOSAL; - prop->sadb_prop_len = SADB_8TO64(sizeof (sadb_prop_t)); - *(uint32_t *)(&prop->sadb_prop_replay) = 0; /* Quick zero-out! */ - - prop->sadb_prop_replay = espstack->ipsecesp_replay_size; - - /* - * Based upon algorithm properties, and what-not, prioritize a - * proposal, based on the ordering of the ESP algorithms in the - * alternatives in the policy rule or socket that was placed - * in the acquire record. - * - * For each action in policy list - * Add combination. If I've hit limit, return. - */ - - for (ap = acqrec->ipsacq_act; ap != NULL; - ap = ap->ipa_next) { - ipsec_alginfo_t *ealg = NULL; - ipsec_alginfo_t *aalg = NULL; - - if (ap->ipa_act.ipa_type != IPSEC_POLICY_APPLY) - continue; - - prot = &ap->ipa_act.ipa_apply; - - if (!(prot->ipp_use_esp)) - continue; - - if (prot->ipp_esp_auth_alg != 0) { - aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH] - [prot->ipp_esp_auth_alg]; - if (aalg == NULL || !ALG_VALID(aalg)) - continue; - } - - ASSERT(prot->ipp_encr_alg > 0); - ealg = ipss->ipsec_alglists[IPSEC_ALG_ENCR] - [prot->ipp_encr_alg]; - if (ealg == NULL || !ALG_VALID(ealg)) - continue; - - comb->sadb_comb_flags = 0; - comb->sadb_comb_reserved = 0; - comb->sadb_comb_encrypt = ealg->alg_id; - comb->sadb_comb_encrypt_minbits = - MAX(prot->ipp_espe_minbits, ealg->alg_ef_minbits); - comb->sadb_comb_encrypt_maxbits = - MIN(prot->ipp_espe_maxbits, ealg->alg_ef_maxbits); - - if (aalg == NULL) { - comb->sadb_comb_auth = 0; - comb->sadb_comb_auth_minbits = 0; - comb->sadb_comb_auth_maxbits = 0; - } else { - comb->sadb_comb_auth = aalg->alg_id; - comb->sadb_comb_auth_minbits = - MAX(prot->ipp_espa_minbits, aalg->alg_ef_minbits); - comb->sadb_comb_auth_maxbits = - MIN(prot->ipp_espa_maxbits, aalg->alg_ef_maxbits); - } - - /* - * The following may be based on algorithm - * properties, but in the meantime, we just pick - * some good, sensible numbers. Key mgmt. can - * (and perhaps should) be the place to finalize - * such decisions. - */ - - /* - * No limits on allocations, since we really don't - * support that concept currently. - */ - comb->sadb_comb_soft_allocations = 0; - comb->sadb_comb_hard_allocations = 0; - - /* - * These may want to come from policy rule.. - */ - comb->sadb_comb_soft_bytes = - espstack->ipsecesp_default_soft_bytes; - comb->sadb_comb_hard_bytes = - espstack->ipsecesp_default_hard_bytes; - comb->sadb_comb_soft_addtime = - espstack->ipsecesp_default_soft_addtime; - comb->sadb_comb_hard_addtime = - espstack->ipsecesp_default_hard_addtime; - comb->sadb_comb_soft_usetime = - espstack->ipsecesp_default_soft_usetime; - comb->sadb_comb_hard_usetime = - espstack->ipsecesp_default_hard_usetime; - - prop->sadb_prop_len += SADB_8TO64(sizeof (*comb)); - if (--combs == 0) - break; /* out of space.. */ - comb++; - } -} - -/* - * Prepare and actually send the SADB_ACQUIRE message to PF_KEY. - */ -static void -esp_send_acquire(ipsacq_t *acqrec, mblk_t *extended, netstack_t *ns) -{ - uint_t combs; - sadb_msg_t *samsg; - sadb_prop_t *prop; - mblk_t *pfkeymp, *msgmp; - ipsecesp_stack_t *espstack = ns->netstack_ipsecesp; - ipsec_stack_t *ipss = ns->netstack_ipsec; - - ESP_BUMP_STAT(espstack, acquire_requests); - - if (espstack->esp_pfkey_q == NULL) { - mutex_exit(&acqrec->ipsacq_lock); - return; - } - - /* Set up ACQUIRE. */ - pfkeymp = sadb_setup_acquire(acqrec, SADB_SATYPE_ESP, - ns->netstack_ipsec); - if (pfkeymp == NULL) { - esp0dbg(("sadb_setup_acquire failed.\n")); - mutex_exit(&acqrec->ipsacq_lock); - return; - } - ASSERT(RW_READ_HELD(&ipss->ipsec_alg_lock)); - combs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH] * - ipss->ipsec_nalgs[IPSEC_ALG_ENCR]; - msgmp = pfkeymp->b_cont; - samsg = (sadb_msg_t *)(msgmp->b_rptr); - - /* Insert proposal here. */ - - prop = (sadb_prop_t *)(((uint64_t *)samsg) + samsg->sadb_msg_len); - esp_insert_prop(prop, acqrec, combs, ns); - samsg->sadb_msg_len += prop->sadb_prop_len; - msgmp->b_wptr += SADB_64TO8(samsg->sadb_msg_len); - - rw_exit(&ipss->ipsec_alg_lock); - - /* - * Must mutex_exit() before sending PF_KEY message up, in - * order to avoid recursive mutex_enter() if there are no registered - * listeners. - * - * Once I've sent the message, I'm cool anyway. - */ - mutex_exit(&acqrec->ipsacq_lock); - if (extended != NULL) { - putnext(espstack->esp_pfkey_q, extended); - } - putnext(espstack->esp_pfkey_q, pfkeymp); -} - /* XXX refactor me */ /* * Handle the SADB_GETSPI message. Create a larval SA. @@ -1811,11 +1567,9 @@ esp_log_bad_auth(mblk_t *mp, ip_recv_attr_t *ira) /* * Invoked for outbound packets after ESP processing. If the packet * also requires AH, performs the AH SA selection and AH processing. - * Returns B_TRUE if the AH processing was not needed or if it was - * performed successfully. Returns B_FALSE and consumes the passed mblk - * if AH processing was required but could not be performed. * - * Returns data_mp unless data_mp was consumed/queued. + * Returns data_mp (possibly with AH added) unless data_mp was consumed + * due to an error, or queued due to async. crypto or an ACQUIRE trigger. */ static mblk_t * esp_do_outbound_ah(mblk_t *data_mp, ip_xmit_attr_t *ixa) diff --git a/usr/src/uts/common/inet/ip/sadb.c b/usr/src/uts/common/inet/ip/sadb.c index 2f59916591ce..d6dfa5705f59 100644 --- a/usr/src/uts/common/inet/ip/sadb.c +++ b/usr/src/uts/common/inet/ip/sadb.c @@ -22,6 +22,7 @@ * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2017 Joyent, Inc. */ #include @@ -74,8 +75,7 @@ * of falling under export control, it was safe to link it in there. */ -static mblk_t *sadb_extended_acquire(ipsec_selector_t *, ipsec_policy_t *, - ipsec_action_t *, boolean_t, uint32_t, uint32_t, sadb_sens_t *, +static uint8_t *sadb_action_to_ecomb(uint8_t *, uint8_t *, ipsec_action_t *, netstack_t *); static ipsa_t *sadb_torch_assoc(isaf_t *, ipsa_t *); static void sadb_destroy_acqlist(iacqf_t **, uint_t, boolean_t, @@ -83,7 +83,6 @@ static void sadb_destroy_acqlist(iacqf_t **, uint_t, boolean_t, static void sadb_destroy(sadb_t *, netstack_t *); static mblk_t *sadb_sa2msg(ipsa_t *, sadb_msg_t *); static ts_label_t *sadb_label_from_sens(sadb_sens_t *, uint64_t *); -static sadb_sens_t *sadb_make_sens_ext(ts_label_t *tsl, int *len); static time_t sadb_add_time(time_t, uint64_t); static void lifetime_fuzz(ipsa_t *); @@ -4844,1027 +4843,1250 @@ sadb_checkacquire(iacqf_t *bucket, ipsec_action_t *ap, ipsec_policy_t *pp, } /* - * For this mblk, insert a new acquire record. Assume bucket contains addrs - * of all of the same length. Give up (and drop) if memory - * cannot be allocated for a new one; otherwise, invoke callback to - * send the acquire up.. - * - * In cases where we need both AH and ESP, add the SA to the ESP ACQUIRE - * list. The ah_add_sa_finish() routines can look at the packet's attached - * attributes and handle this case specially. + * Generate an SADB_ACQUIRE base message mblk, including KEYSOCK_OUT metadata. + * In other words, this will return, upon success, a two-mblk chain. */ -void -sadb_acquire(mblk_t *datamp, ip_xmit_attr_t *ixa, boolean_t need_ah, - boolean_t need_esp) +static inline mblk_t * +sadb_acquire_msg_base(minor_t serial, uint8_t satype, uint32_t seq, pid_t pid) { - mblk_t *asyncmp; - sadbp_t *spp; - sadb_t *sp; - ipsacq_t *newbie; - iacqf_t *bucket; - mblk_t *extended; - ipha_t *ipha = (ipha_t *)datamp->b_rptr; - ip6_t *ip6h = (ip6_t *)datamp->b_rptr; - uint32_t *src, *dst, *isrc, *idst; - ipsec_policy_t *pp = ixa->ixa_ipsec_policy; - ipsec_action_t *ap = ixa->ixa_ipsec_action; - sa_family_t af; - int hashoffset; - uint32_t seq; - uint64_t unique_id = 0; - ipsec_selector_t sel; - boolean_t tunnel_mode = (ixa->ixa_flags & IXAF_IPSEC_TUNNEL) != 0; - ts_label_t *tsl = NULL; - netstack_t *ns = ixa->ixa_ipst->ips_netstack; - ipsec_stack_t *ipss = ns->netstack_ipsec; - sadb_sens_t *sens = NULL; - int sens_len; + mblk_t *mp; + sadb_msg_t *samsg; - ASSERT((pp != NULL) || (ap != NULL)); + mp = sadb_keysock_out(serial); + if (mp == NULL) + return (NULL); + mp->b_cont = allocb(sizeof (sadb_msg_t), BPRI_HI); + if (mp->b_cont == NULL) { + freeb(mp); + return (NULL); + } - ASSERT(need_ah != NULL || need_esp != NULL); + samsg = (sadb_msg_t *)mp->b_cont->b_rptr; + mp->b_cont->b_wptr += sizeof (*samsg); + samsg->sadb_msg_version = PF_KEY_V2; + samsg->sadb_msg_type = SADB_ACQUIRE; + samsg->sadb_msg_errno = 0; + samsg->sadb_msg_reserved = 0; + samsg->sadb_msg_satype = satype; + samsg->sadb_msg_seq = seq; + samsg->sadb_msg_pid = pid; - /* Assign sadb pointers */ - if (need_esp) { /* ESP for AH+ESP */ - ipsecesp_stack_t *espstack = ns->netstack_ipsecesp; + return (mp); +} - spp = &espstack->esp_sadb; - } else { - ipsecah_stack_t *ahstack = ns->netstack_ipsecah; +/* + * Generate address and TX/MLS sensitivity label PF_KEY extensions that are + * common to both regular and extended ACQUIREs. + */ +static mblk_t * +sadb_acquire_msg_common(ipsec_selector_t *sel, ipsec_policy_t *pp, + ipsec_action_t *ap, boolean_t tunnel_mode, ts_label_t *tsl, + sadb_sens_t *sens) +{ + size_t len; + mblk_t *mp; + uint8_t *start, *cur, *end; + uint32_t *saddrptr, *daddrptr; + sa_family_t af; + ipsec_action_t *oldap; + ipsec_selkey_t *ipsl; + uint8_t proto, pfxlen; + uint16_t lport, rport; + int senslen = 0; - spp = &ahstack->ah_sadb; + /* + * Get action pointer set if it isn't already. + */ + oldap = ap; + if (pp != NULL) { + ap = pp->ipsp_act; + if (ap == NULL) + ap = oldap; } - sp = (ixa->ixa_flags & IXAF_IS_IPV4) ? &spp->s_v4 : &spp->s_v6; - if (is_system_labeled()) - tsl = ixa->ixa_tsl; + /* + * Biggest-case scenario: + * 4x (sadb_address_t + struct sockaddr_in6) + * (src, dst, isrc, idst) + * (COMING SOON, 6x, because of triggering-packet contents.) + * sadb_x_kmc_t + * sadb_sens_t + * And wiggle room for label bitvectors. Luckily there are + * programmatic ways to find it. + */ + len = 4 * (sizeof (sadb_address_t) + sizeof (struct sockaddr_in6)); - if (ap == NULL) - ap = pp->ipsp_act; + /* Figure out full and proper length of sensitivity labels. */ + if (sens != NULL) { + ASSERT(tsl == NULL); + senslen = SADB_64TO8(sens->sadb_sens_len); + } else if (tsl != NULL) { + senslen = sadb_sens_len_from_label(tsl); + } +#ifdef DEBUG + else { + ASSERT(senslen == 0); + } +#endif /* DEBUG */ + len += senslen; - ASSERT(ap != NULL); + mp = allocb(len, BPRI_HI); + if (mp == NULL) + return (NULL); - if (ap->ipa_act.ipa_apply.ipp_use_unique || tunnel_mode) - unique_id = SA_FORM_UNIQUE_ID(ixa); + start = mp->b_rptr; + end = start + len; + cur = start; /* - * Set up an ACQUIRE record. - * - * Immediately, make sure the ACQUIRE sequence number doesn't slip - * below the lowest point allowed in the kernel. (In other words, - * make sure the high bit on the sequence number is set.) + * Address extensions first, from most-recently-defined to least. + * (This should immediately trigger surprise or verify robustness on + * older apps, like in.iked.) */ + if (tunnel_mode) { + /* + * Form inner address extensions based NOT on the inner + * selectors (i.e. the packet data), but on the policy's + * selector key (i.e. the policy's selector information). + * + * NOTE: The position of IPv4 and IPv6 addresses is the + * same in ipsec_selkey_t (unless the compiler does very + * strange things with unions, consult your local C language + * lawyer for details). + */ + ASSERT(pp != NULL); - seq = keysock_next_seq(ns) | IACQF_LOWEST_SEQ; + ipsl = &(pp->ipsp_sel->ipsl_key); + if (ipsl->ipsl_valid & IPSL_IPV4) { + af = AF_INET; + ASSERT(sel->ips_protocol == IPPROTO_ENCAP); + ASSERT(!(ipsl->ipsl_valid & IPSL_IPV6)); + } else { + af = AF_INET6; + ASSERT(sel->ips_protocol == IPPROTO_IPV6); + ASSERT(ipsl->ipsl_valid & IPSL_IPV6); + } - if (IPH_HDR_VERSION(ipha) == IP_VERSION) { - src = (uint32_t *)&ipha->ipha_src; - dst = (uint32_t *)&ipha->ipha_dst; - af = AF_INET; - hashoffset = OUTBOUND_HASH_V4(sp, ipha->ipha_dst); - ASSERT(ixa->ixa_flags & IXAF_IS_IPV4); - } else { - ASSERT(IPH_HDR_VERSION(ipha) == IPV6_VERSION); - src = (uint32_t *)&ip6h->ip6_src; - dst = (uint32_t *)&ip6h->ip6_dst; - af = AF_INET6; - hashoffset = OUTBOUND_HASH_V6(sp, ip6h->ip6_dst); - ASSERT(!(ixa->ixa_flags & IXAF_IS_IPV4)); - } + if (ipsl->ipsl_valid & IPSL_LOCAL_ADDR) { + saddrptr = (uint32_t *)(&ipsl->ipsl_local); + pfxlen = ipsl->ipsl_local_pfxlen; + } else { + saddrptr = (uint32_t *)(&ipv6_all_zeros); + pfxlen = 0; + } + /* XXX What about ICMP type/code? */ + lport = (ipsl->ipsl_valid & IPSL_LOCAL_PORT) ? + ipsl->ipsl_lport : 0; + proto = (ipsl->ipsl_valid & IPSL_PROTOCOL) ? + ipsl->ipsl_proto : 0; - if (tunnel_mode) { - if (pp == NULL) { - /* - * Tunnel mode with no policy pointer means this is a - * reflected ICMP (like a ECHO REQUEST) that came in - * with self-encapsulated protection. Until we better - * support this, drop the packet. - */ - ip_drop_packet(datamp, B_FALSE, NULL, - DROPPER(ipss, ipds_spd_got_selfencap), - &ipss->ipsec_spd_dropper); - return; + cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_SRC, + af, saddrptr, lport, proto, pfxlen); + if (cur == NULL) { + freeb(mp); + return (NULL); } - /* Snag inner addresses. */ - isrc = ixa->ixa_ipsec_insrc; - idst = ixa->ixa_ipsec_indst; - } else { - isrc = idst = NULL; - } - /* - * Check buckets to see if there is an existing entry. If so, - * grab it. sadb_checkacquire locks newbie if found. - */ - bucket = &(sp->sdb_acq[hashoffset]); - mutex_enter(&bucket->iacqf_lock); - newbie = sadb_checkacquire(bucket, ap, pp, src, dst, isrc, idst, - unique_id, tsl); + if (ipsl->ipsl_valid & IPSL_REMOTE_ADDR) { + daddrptr = (uint32_t *)(&ipsl->ipsl_remote); + pfxlen = ipsl->ipsl_remote_pfxlen; + } else { + daddrptr = (uint32_t *)(&ipv6_all_zeros); + pfxlen = 0; + } + /* XXX What about ICMP type/code? */ + rport = (ipsl->ipsl_valid & IPSL_REMOTE_PORT) ? + ipsl->ipsl_rport : 0; - if (newbie == NULL) { + cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_DST, + af, daddrptr, rport, proto, pfxlen); + if (cur == NULL) { + freeb(mp); + return (NULL); + } /* - * Otherwise, allocate a new one. + * TODO - if we go to 3884's dream of transport mode IP-in-IP + * _with_ inner-packet address selectors, we'll need to further + * distinguish tunnel mode here. For now, having inner + * addresses and/or ports is sufficient. + * + * Meanwhile, whack proto/ports to reflect IP-in-IP for the + * outer addresses. */ - newbie = kmem_zalloc(sizeof (*newbie), KM_NOSLEEP); - if (newbie == NULL) { - mutex_exit(&bucket->iacqf_lock); - ip_drop_packet(datamp, B_FALSE, NULL, - DROPPER(ipss, ipds_sadb_acquire_nomem), - &ipss->ipsec_sadb_dropper); - return; - } - newbie->ipsacq_policy = pp; + proto = sel->ips_protocol; /* Either _ENCAP or _IPV6 */ + lport = rport = 0; + } else if ((ap != NULL) && (!ap->ipa_want_unique)) { + /* + * For cases when the policy calls out specific ports (or not). + */ + proto = 0; + lport = 0; + rport = 0; if (pp != NULL) { - IPPOL_REFHOLD(pp); + ipsl = &(pp->ipsp_sel->ipsl_key); + if (ipsl->ipsl_valid & IPSL_PROTOCOL) + proto = ipsl->ipsl_proto; + if (ipsl->ipsl_valid & IPSL_REMOTE_PORT) + rport = ipsl->ipsl_rport; + if (ipsl->ipsl_valid & IPSL_LOCAL_PORT) + lport = ipsl->ipsl_lport; } - IPACT_REFHOLD(ap); - newbie->ipsacq_act = ap; - newbie->ipsacq_linklock = &bucket->iacqf_lock; - newbie->ipsacq_next = bucket->iacqf_ipsacq; - newbie->ipsacq_ptpn = &bucket->iacqf_ipsacq; - if (newbie->ipsacq_next != NULL) - newbie->ipsacq_next->ipsacq_ptpn = &newbie->ipsacq_next; - - bucket->iacqf_ipsacq = newbie; - mutex_init(&newbie->ipsacq_lock, NULL, MUTEX_DEFAULT, NULL); - mutex_enter(&newbie->ipsacq_lock); + } else { + /* + * For require-unique-SA policies. + */ + proto = sel->ips_protocol; + lport = sel->ips_local_port; + rport = sel->ips_remote_port; } /* - * XXX MLS does it actually help us to drop the bucket lock here? - * we have inserted a half-built, locked acquire record into the - * bucket. any competing thread will now be able to lock the bucket - * to scan it, but will immediately pile up on the new acquire - * record's lock; I don't think we gain anything here other than to - * disperse blame for lock contention. - * - * we might be able to dispense with acquire record locks entirely.. - * just use the bucket locks.. + * Regular addresses. These are outer-packet ones for tunnel mode. + * Or for transport mode, the regulard address & port information. */ - - mutex_exit(&bucket->iacqf_lock); + af = sel->ips_isv4 ? AF_INET : AF_INET6; /* - * This assert looks silly for now, but we may need to enter newbie's - * mutex during a search. + * NOTE: The position of IPv4 and IPv6 addresses is the same in + * ipsec_selector_t. */ - ASSERT(MUTEX_HELD(&newbie->ipsacq_lock)); + cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_SRC, af, + (uint32_t *)(&sel->ips_local_addr_v6), lport, proto, 0); + if (cur == NULL) { + freeb(mp); + return (NULL); + } - /* - * Make the ip_xmit_attr_t into something we can queue. - * If no memory it frees datamp. + cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_DST, af, + (uint32_t *)(&sel->ips_remote_addr_v6), rport, proto, 0); + if (cur == NULL) { + freeb(mp); + return (NULL); + } + + /* + * If present, generate a sensitivity label. */ - asyncmp = ip_xmit_attr_to_mblk(ixa); - if (asyncmp != NULL) - linkb(asyncmp, datamp); + if (cur + senslen > end) { + freeb(mp); + return (NULL); + } + if (sens != NULL) { + /* Explicit sadb_sens_t, usually from inverse-ACQUIRE. */ + bcopy(sens, cur, senslen); + } else if (tsl != NULL) { + /* Generate sadb_sens_t from ACQUIRE source. */ + sadb_sens_from_label((sadb_sens_t *)cur, SADB_EXT_SENSITIVITY, + tsl, senslen); + } +#ifdef DEBUG + else { + ASSERT(senslen == 0); + } +#endif /* DEBUG */ + cur += senslen; + mp->b_wptr = cur; - /* Queue up packet. Use b_next. */ + return (mp); +} - if (asyncmp == NULL) { - /* Statistics for allocation failure */ - if (ixa->ixa_flags & IXAF_IS_IPV4) { - BUMP_MIB(&ixa->ixa_ipst->ips_ip_mib, - ipIfStatsOutDiscards); - } else { - BUMP_MIB(&ixa->ixa_ipst->ips_ip6_mib, - ipIfStatsOutDiscards); +/* + * Generate a regular ACQUIRE's proposal extension and KMC information.. + */ +static mblk_t * +sadb_acquire_prop(ipsec_action_t *ap, netstack_t *ns, boolean_t do_esp) +{ + ipsec_stack_t *ipss = ns->netstack_ipsec; + ipsecesp_stack_t *espstack = ns->netstack_ipsecesp; + ipsecah_stack_t *ahstack = ns->netstack_ipsecah; + mblk_t *mp = NULL; + sadb_prop_t *prop; + sadb_comb_t *comb; + ipsec_action_t *walker; + int ncombs, allocsize, ealgid, aalgid, aminbits, amaxbits, eminbits, + emaxbits, replay; + uint64_t softbytes, hardbytes, softaddtime, hardaddtime, softusetime, + hardusetime; + uint32_t kmc = 0, kmp = 0; + + /* + * Since it's an rwlock read, AND writing to the IPsec algorithms is + * rare, just acquire it once up top, and drop it upon return. + */ + rw_enter(&ipss->ipsec_alg_lock, RW_READER); + if (do_esp) { + uint64_t num_aalgs, num_ealgs; + + if (espstack->esp_kstats == NULL) + goto bail; + + num_aalgs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH]; + num_ealgs = ipss->ipsec_nalgs[IPSEC_ALG_ENCR]; + if (num_ealgs == 0) + goto bail; /* IPsec not loaded yet, apparently. */ + num_aalgs++; /* No-auth or self-auth-crypto ESP. */ + + /* Use netstack's maximum loaded algorithms... */ + ncombs = num_ealgs * num_aalgs; + replay = espstack->ipsecesp_replay_size; + } else { + if (ahstack->ah_kstats == NULL) + goto bail; + + ncombs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH]; + + if (ncombs == 0) + goto bail; /* IPsec not loaded yet, apparently. */ + replay = ahstack->ipsecah_replay_size; + } + + allocsize = sizeof (*prop) + ncombs * sizeof (*comb) + + sizeof (sadb_x_kmc_t); + mp = allocb(allocsize, BPRI_HI); + if (mp == NULL) + goto bail; + prop = (sadb_prop_t *)mp->b_rptr; + mp->b_wptr += sizeof (*prop); + comb = (sadb_comb_t *)mp->b_wptr; + /* Decrement allocsize, if it goes to or below 0, stop. */ + allocsize -= sizeof (*prop); + prop->sadb_prop_exttype = SADB_EXT_PROPOSAL; + prop->sadb_prop_len = SADB_8TO64(sizeof (*prop)); + *(uint32_t *)(&prop->sadb_prop_replay) = 0; /* Quick zero-out! */ + prop->sadb_prop_replay = replay; + + /* + * Based upon algorithm properties, and what-not, prioritize a + * proposal, based on the ordering of the ESP algorithms in the + * alternatives in the policy rule or socket that was placed + * in the acquire record. + * + * For each action in policy list + * Add combination. + * I should not hit it, but if I've hit limit, return. + */ + + for (walker = ap; walker != NULL; walker = walker->ipa_next) { + ipsec_alginfo_t *ealg, *aalg; + ipsec_prot_t *prot; + + if (walker->ipa_act.ipa_type != IPSEC_POLICY_APPLY) + continue; + + prot = &walker->ipa_act.ipa_apply; + if (walker->ipa_act.ipa_apply.ipp_km_proto != 0) + kmp = walker->ipa_act.ipa_apply.ipp_km_proto; + if (walker->ipa_act.ipa_apply.ipp_km_cookie != 0) + kmc = walker->ipa_act.ipa_apply.ipp_km_cookie; + if (walker->ipa_act.ipa_apply.ipp_replay_depth) { + prop->sadb_prop_replay = + walker->ipa_act.ipa_apply.ipp_replay_depth; } - ip_drop_output("No memory for asyncmp", datamp, NULL); - freemsg(datamp); - } else if (newbie->ipsacq_numpackets == 0) { - /* First one. */ - newbie->ipsacq_mp = asyncmp; - newbie->ipsacq_numpackets = 1; - newbie->ipsacq_expire = gethrestime_sec(); - /* - * Extended ACQUIRE with both AH+ESP will use ESP's timeout - * value. - */ - newbie->ipsacq_expire += *spp->s_acquire_timeout; - newbie->ipsacq_seq = seq; - newbie->ipsacq_addrfam = af; - newbie->ipsacq_srcport = ixa->ixa_ipsec_src_port; - newbie->ipsacq_dstport = ixa->ixa_ipsec_dst_port; - newbie->ipsacq_icmp_type = ixa->ixa_ipsec_icmp_type; - newbie->ipsacq_icmp_code = ixa->ixa_ipsec_icmp_code; - if (tunnel_mode) { - newbie->ipsacq_inneraddrfam = ixa->ixa_ipsec_inaf; - newbie->ipsacq_proto = ixa->ixa_ipsec_inaf == AF_INET6 ? - IPPROTO_IPV6 : IPPROTO_ENCAP; - newbie->ipsacq_innersrcpfx = ixa->ixa_ipsec_insrcpfx; - newbie->ipsacq_innerdstpfx = ixa->ixa_ipsec_indstpfx; - IPSA_COPY_ADDR(newbie->ipsacq_innersrc, - ixa->ixa_ipsec_insrc, ixa->ixa_ipsec_inaf); - IPSA_COPY_ADDR(newbie->ipsacq_innerdst, - ixa->ixa_ipsec_indst, ixa->ixa_ipsec_inaf); + if (do_esp) { + if (!prot->ipp_use_esp) + continue; + + if (prot->ipp_esp_auth_alg != 0) { + aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH] + [prot->ipp_esp_auth_alg]; + if (aalg == NULL || !ALG_VALID(aalg)) + continue; + } else + aalg = NULL; + + ASSERT(prot->ipp_encr_alg > 0); + ealg = ipss->ipsec_alglists[IPSEC_ALG_ENCR] + [prot->ipp_encr_alg]; + if (ealg == NULL || !ALG_VALID(ealg)) + continue; + + /* + * These may want to come from policy rule.. + */ + softbytes = espstack->ipsecesp_default_soft_bytes; + hardbytes = espstack->ipsecesp_default_hard_bytes; + softaddtime = espstack->ipsecesp_default_soft_addtime; + hardaddtime = espstack->ipsecesp_default_hard_addtime; + softusetime = espstack->ipsecesp_default_soft_usetime; + hardusetime = espstack->ipsecesp_default_hard_usetime; } else { - newbie->ipsacq_proto = ixa->ixa_ipsec_proto; - } - newbie->ipsacq_unique_id = unique_id; + if (!prot->ipp_use_ah) + continue; + ealg = NULL; + aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH] + [prot->ipp_auth_alg]; + if (aalg == NULL || !ALG_VALID(aalg)) + continue; - if (ixa->ixa_tsl != NULL) { - label_hold(ixa->ixa_tsl); - newbie->ipsacq_tsl = ixa->ixa_tsl; + /* + * These may want to come from policy rule.. + */ + softbytes = ahstack->ipsecah_default_soft_bytes; + hardbytes = ahstack->ipsecah_default_hard_bytes; + softaddtime = ahstack->ipsecah_default_soft_addtime; + hardaddtime = ahstack->ipsecah_default_hard_addtime; + softusetime = ahstack->ipsecah_default_soft_usetime; + hardusetime = ahstack->ipsecah_default_hard_usetime; } - } else { - /* Scan to the end of the list & insert. */ - mblk_t *lastone = newbie->ipsacq_mp; - while (lastone->b_next != NULL) - lastone = lastone->b_next; - lastone->b_next = asyncmp; - if (newbie->ipsacq_numpackets++ == ipsacq_maxpackets) { - newbie->ipsacq_numpackets = ipsacq_maxpackets; - lastone = newbie->ipsacq_mp; - newbie->ipsacq_mp = lastone->b_next; - lastone->b_next = NULL; + if (ealg == NULL) { + ealgid = eminbits = emaxbits = 0; + } else { + ealgid = ealg->alg_id; + eminbits = + MAX(prot->ipp_espe_minbits, ealg->alg_ef_minbits); + emaxbits = + MIN(prot->ipp_espe_maxbits, ealg->alg_ef_maxbits); + } - /* Freeing the async message */ - lastone = ip_xmit_attr_free_mblk(lastone); - ip_drop_packet(lastone, B_FALSE, NULL, - DROPPER(ipss, ipds_sadb_acquire_toofull), - &ipss->ipsec_sadb_dropper); + if (aalg == NULL) { + aalgid = aminbits = amaxbits = 0; } else { - IP_ACQUIRE_STAT(ipss, qhiwater, - newbie->ipsacq_numpackets); + aalgid = aalg->alg_id; + aminbits = MAX(prot->ipp_espa_minbits, + aalg->alg_ef_minbits); + amaxbits = MIN(prot->ipp_espa_maxbits, + aalg->alg_ef_maxbits); + } + + comb->sadb_comb_flags = 0; + comb->sadb_comb_reserved = 0; + comb->sadb_comb_encrypt = ealgid; + comb->sadb_comb_encrypt_minbits = eminbits; + comb->sadb_comb_encrypt_maxbits = emaxbits; + comb->sadb_comb_auth = aalgid; + comb->sadb_comb_auth_minbits = aminbits; + comb->sadb_comb_auth_maxbits = amaxbits; + comb->sadb_comb_soft_allocations = 0; + comb->sadb_comb_hard_allocations = 0; + comb->sadb_comb_soft_bytes = softbytes; + comb->sadb_comb_hard_bytes = hardbytes; + comb->sadb_comb_soft_addtime = softaddtime; + comb->sadb_comb_hard_addtime = hardaddtime; + comb->sadb_comb_soft_usetime = softusetime; + comb->sadb_comb_hard_usetime = hardusetime; + + prop->sadb_prop_len += SADB_8TO64(sizeof (*comb)); + mp->b_wptr += sizeof (*comb); + allocsize -= sizeof (*comb); + /* Should never dip BELOW sizeof (KM cookie extension). */ + ASSERT3S(allocsize, >=, sizeof (sadb_x_kmc_t)); + if (allocsize <= sizeof (sadb_x_kmc_t)) + break; /* out of space.. */ + comb++; + } + + /* Don't include KMC extension if there's no room. */ + if (((kmp != 0) || (kmc != 0)) && allocsize >= sizeof (sadb_x_kmc_t)) { + if (sadb_make_kmc_ext(mp->b_wptr, + mp->b_wptr + sizeof (sadb_x_kmc_t), kmp, kmc) == NULL) { + freeb(mp); + mp = NULL; + goto bail; } + mp->b_wptr += sizeof (sadb_x_kmc_t); + prop->sadb_prop_len += SADB_8TO64(sizeof (sadb_x_kmc_t)); } - /* - * Reset addresses. Set them to the most recently added mblk chain, - * so that the address pointers in the acquire record will point - * at an mblk still attached to the acquire list. - */ +bail: + rw_exit(&ipss->ipsec_alg_lock); + return (mp); +} - newbie->ipsacq_srcaddr = src; - newbie->ipsacq_dstaddr = dst; +/* + * Generate an extended ACQUIRE's extended-proposal extension. + */ +/* ARGSUSED */ +static mblk_t * +sadb_acquire_extended_prop(ipsec_action_t *ap, netstack_t *ns) +{ + sadb_prop_t *eprop; + uint8_t *cur, *end; + mblk_t *mp; + int allocsize, numecombs = 0, numalgdescs = 0; + uint32_t kmc = 0, kmp = 0, replay = 0; + ipsec_action_t *walker; - /* - * If the acquire record has more than one queued packet, we've - * already sent an ACQUIRE, and don't need to repeat ourself. - */ - if (newbie->ipsacq_seq != seq || newbie->ipsacq_numpackets > 1) { - /* I have an acquire outstanding already! */ - mutex_exit(&newbie->ipsacq_lock); - return; - } + allocsize = sizeof (*eprop); - if (!keysock_extended_reg(ns)) - goto punt_extended; /* - * Construct an extended ACQUIRE. There are logging - * opportunities here in failure cases. + * Going to walk through the action list twice. Once for allocation + * measurement, and once for actual construction. */ - bzero(&sel, sizeof (sel)); - sel.ips_isv4 = (ixa->ixa_flags & IXAF_IS_IPV4) != 0; - if (tunnel_mode) { - sel.ips_protocol = (ixa->ixa_ipsec_inaf == AF_INET) ? - IPPROTO_ENCAP : IPPROTO_IPV6; - } else { - sel.ips_protocol = ixa->ixa_ipsec_proto; - sel.ips_local_port = ixa->ixa_ipsec_src_port; - sel.ips_remote_port = ixa->ixa_ipsec_dst_port; - } - sel.ips_icmp_type = ixa->ixa_ipsec_icmp_type; - sel.ips_icmp_code = ixa->ixa_ipsec_icmp_code; - sel.ips_is_icmp_inv_acq = 0; - if (af == AF_INET) { - sel.ips_local_addr_v4 = ipha->ipha_src; - sel.ips_remote_addr_v4 = ipha->ipha_dst; - } else { - sel.ips_local_addr_v6 = ip6h->ip6_src; - sel.ips_remote_addr_v6 = ip6h->ip6_dst; - } + for (walker = ap; walker != NULL; walker = walker->ipa_next) { + ipsec_prot_t *ipp; - extended = sadb_keysock_out(0); - if (extended == NULL) - goto punt_extended; - - if (ixa->ixa_tsl != NULL) { /* - * XXX MLS correct condition here? - * XXX MLS other credential attributes in acquire? - * XXX malloc failure? don't fall back to original? + * Skip non-IPsec policies */ - sens = sadb_make_sens_ext(ixa->ixa_tsl, &sens_len); + if (walker->ipa_act.ipa_type != IPSEC_ACT_APPLY) + continue; + + ipp = &walker->ipa_act.ipa_apply; - if (sens == NULL) { - freeb(extended); - goto punt_extended; + if (walker->ipa_act.ipa_apply.ipp_km_proto) + kmp = ipp->ipp_km_proto; + if (walker->ipa_act.ipa_apply.ipp_km_cookie) + kmc = ipp->ipp_km_cookie; + if (walker->ipa_act.ipa_apply.ipp_replay_depth) + replay = ipp->ipp_replay_depth; + + if (ipp->ipp_use_ah) + numalgdescs++; + if (ipp->ipp_use_esp) { + numalgdescs++; + if (ipp->ipp_use_espa) + numalgdescs++; } + + numecombs++; } + ASSERT(numecombs > 0); - extended->b_cont = sadb_extended_acquire(&sel, pp, ap, tunnel_mode, - seq, 0, sens, ns); + allocsize += numecombs * sizeof (sadb_x_ecomb_t) + + numalgdescs * sizeof (sadb_x_algdesc_t) + sizeof (sadb_x_kmc_t); + mp = allocb(allocsize, BPRI_HI); + if (mp == NULL) + return (NULL); + eprop = (sadb_prop_t *)mp->b_rptr; + end = mp->b_rptr + allocsize; + cur = mp->b_rptr + sizeof (*eprop); - if (sens != NULL) - kmem_free(sens, sens_len); + eprop->sadb_prop_exttype = SADB_X_EXT_EPROP; + eprop->sadb_x_prop_ereserved = 0; + eprop->sadb_x_prop_numecombs = 0; + *(uint32_t *)(&eprop->sadb_prop_replay) = 0; /* Quick zero-out! */ + /* Pick ESP's replay default if need be. */ + eprop->sadb_prop_replay = (replay == 0) ? + ns->netstack_ipsecesp->ipsecesp_replay_size : replay; - if (extended->b_cont == NULL) { - freeb(extended); - goto punt_extended; + /* This time, walk through and actually allocate. */ + for (walker = ap; walker != NULL; walker = walker->ipa_next) { + /* + * Skip non-IPsec policies + */ + if (walker->ipa_act.ipa_type != IPSEC_ACT_APPLY) + continue; + cur = sadb_action_to_ecomb(cur, end, walker, ns); + if (cur == NULL) { + /* NOTE: inverse-ACQUIRE should note this as ENOMEM. */ + freeb(mp); + return (NULL); + } + eprop->sadb_x_prop_numecombs++; } - /* - * Send an ACQUIRE message (and possible an extended ACQUIRE) based on - * this new record. The send-acquire callback assumes that acqrec is - * already locked. - */ - (*spp->s_acqfn)(newbie, extended, ns); - return; + ASSERT(end - cur >= sizeof (sadb_x_kmc_t)); + if ((kmp != 0) || (kmc != 0)) { + cur = sadb_make_kmc_ext(cur, end, kmp, kmc); + if (cur == NULL) { + freeb(mp); + return (NULL); + } + } + mp->b_wptr = cur; + eprop->sadb_prop_len = SADB_8TO64(cur - mp->b_rptr); -punt_extended: - (*spp->s_acqfn)(newbie, NULL, ns); + return (mp); } /* - * Unlink and free an acquire record. + * For this mblk, insert a new acquire record. Assume bucket contains addrs + * of all of the same length. Give up (and drop) if memory + * cannot be allocated for a new one; otherwise, invoke callback to + * send the acquire up.. + * + * In cases where we need both AH and ESP, add the SA to the ESP ACQUIRE + * list. The ah_add_sa_finish() routines can look at the packet's attached + * attributes and handle this case specially. */ void -sadb_destroy_acquire(ipsacq_t *acqrec, netstack_t *ns) +sadb_acquire(mblk_t *datamp, ip_xmit_attr_t *ixa, boolean_t need_ah, + boolean_t need_esp) { - mblk_t *mp; + mblk_t *asyncmp, *regular, *extended, *common, *prop, *eprop; + sadbp_t *spp; + sadb_t *sp; + ipsacq_t *newbie; + iacqf_t *bucket; + ipha_t *ipha = (ipha_t *)datamp->b_rptr; + ip6_t *ip6h = (ip6_t *)datamp->b_rptr; + uint32_t *src, *dst, *isrc, *idst; + ipsec_policy_t *pp = ixa->ixa_ipsec_policy; + ipsec_action_t *ap = ixa->ixa_ipsec_action; + sa_family_t af; + int hashoffset; + uint32_t seq; + uint64_t unique_id = 0; + boolean_t tunnel_mode = (ixa->ixa_flags & IXAF_IPSEC_TUNNEL) != 0; + ts_label_t *tsl; + netstack_t *ns = ixa->ixa_ipst->ips_netstack; ipsec_stack_t *ipss = ns->netstack_ipsec; + ipsecesp_stack_t *espstack = ns->netstack_ipsecesp; + ipsecah_stack_t *ahstack = ns->netstack_ipsecah; + ipsec_selector_t sel; + queue_t *q; - ASSERT(MUTEX_HELD(acqrec->ipsacq_linklock)); + ASSERT((pp != NULL) || (ap != NULL)); - if (acqrec->ipsacq_policy != NULL) { - IPPOL_REFRELE(acqrec->ipsacq_policy); - } - if (acqrec->ipsacq_act != NULL) { - IPACT_REFRELE(acqrec->ipsacq_act); + ASSERT(need_ah || need_esp); + + /* Assign sadb pointers */ + if (need_esp) { + /* + * ESP happens first if we need both AH and ESP. + */ + spp = &espstack->esp_sadb; + } else { + spp = &ahstack->ah_sadb; } + sp = (ixa->ixa_flags & IXAF_IS_IPV4) ? &spp->s_v4 : &spp->s_v6; - /* Unlink */ - *(acqrec->ipsacq_ptpn) = acqrec->ipsacq_next; - if (acqrec->ipsacq_next != NULL) - acqrec->ipsacq_next->ipsacq_ptpn = acqrec->ipsacq_ptpn; + if (is_system_labeled()) + tsl = ixa->ixa_tsl; + else + tsl = NULL; - if (acqrec->ipsacq_tsl != NULL) { - label_rele(acqrec->ipsacq_tsl); - acqrec->ipsacq_tsl = NULL; - } + if (ap == NULL) + ap = pp->ipsp_act; + ASSERT(ap != NULL); + + if (ap->ipa_act.ipa_apply.ipp_use_unique || tunnel_mode) + unique_id = SA_FORM_UNIQUE_ID(ixa); /* - * Free hanging mp's. + * Set up an ACQUIRE record. * - * XXX Instead of freemsg(), perhaps use IPSEC_REQ_FAILED. + * Immediately, make sure the ACQUIRE sequence number doesn't slip + * below the lowest point allowed in the kernel. (In other words, + * make sure the high bit on the sequence number is set.) */ - mutex_enter(&acqrec->ipsacq_lock); - while (acqrec->ipsacq_mp != NULL) { - mp = acqrec->ipsacq_mp; - acqrec->ipsacq_mp = mp->b_next; - mp->b_next = NULL; - /* Freeing the async message */ - mp = ip_xmit_attr_free_mblk(mp); - ip_drop_packet(mp, B_FALSE, NULL, - DROPPER(ipss, ipds_sadb_acquire_timeout), - &ipss->ipsec_sadb_dropper); - } - mutex_exit(&acqrec->ipsacq_lock); + seq = keysock_next_seq(ns) | IACQF_LOWEST_SEQ; - /* Free */ - mutex_destroy(&acqrec->ipsacq_lock); - kmem_free(acqrec, sizeof (*acqrec)); -} + if (IPH_HDR_VERSION(ipha) == IP_VERSION) { + src = (uint32_t *)&ipha->ipha_src; + dst = (uint32_t *)&ipha->ipha_dst; + af = AF_INET; + hashoffset = OUTBOUND_HASH_V4(sp, ipha->ipha_dst); + ASSERT(ixa->ixa_flags & IXAF_IS_IPV4); + } else { + ASSERT(IPH_HDR_VERSION(ipha) == IPV6_VERSION); + src = (uint32_t *)&ip6h->ip6_src; + dst = (uint32_t *)&ip6h->ip6_dst; + af = AF_INET6; + hashoffset = OUTBOUND_HASH_V6(sp, ip6h->ip6_dst); + ASSERT(!(ixa->ixa_flags & IXAF_IS_IPV4)); + } -/* - * Destroy an acquire list fanout. - */ -static void -sadb_destroy_acqlist(iacqf_t **listp, uint_t numentries, boolean_t forever, - netstack_t *ns) -{ - int i; - iacqf_t *list = *listp; + if (tunnel_mode) { + if (pp == NULL) { + /* + * Tunnel mode with no policy pointer means this is a + * reflected ICMP (like a ECHO REQUEST) that came in + * with self-encapsulated protection. Until we better + * support this, drop the packet. + */ + ip_drop_packet(datamp, B_FALSE, NULL, + DROPPER(ipss, ipds_spd_got_selfencap), + &ipss->ipsec_spd_dropper); + return; + } + /* Snag inner addresses. */ + isrc = ixa->ixa_ipsec_insrc; + idst = ixa->ixa_ipsec_indst; + } else { + isrc = idst = NULL; + } - if (list == NULL) - return; + /* + * Check buckets to see if there is an existing entry. If so, + * grab it. sadb_checkacquire locks newbie if found. + */ + bucket = &(sp->sdb_acq[hashoffset]); + mutex_enter(&bucket->iacqf_lock); + newbie = sadb_checkacquire(bucket, ap, pp, src, dst, isrc, idst, + unique_id, tsl); - for (i = 0; i < numentries; i++) { - mutex_enter(&(list[i].iacqf_lock)); - while (list[i].iacqf_ipsacq != NULL) - sadb_destroy_acquire(list[i].iacqf_ipsacq, ns); - mutex_exit(&(list[i].iacqf_lock)); - if (forever) - mutex_destroy(&(list[i].iacqf_lock)); - } + if (newbie == NULL) { + /* + * Otherwise, allocate a new one. + */ + newbie = kmem_zalloc(sizeof (*newbie), KM_NOSLEEP); + if (newbie == NULL) { + mutex_exit(&bucket->iacqf_lock); + ip_drop_packet(datamp, B_FALSE, NULL, + DROPPER(ipss, ipds_sadb_acquire_nomem), + &ipss->ipsec_sadb_dropper); + return; + } + newbie->ipsacq_policy = pp; + if (pp != NULL) { + IPPOL_REFHOLD(pp); + } + IPACT_REFHOLD(ap); + newbie->ipsacq_act = ap; + newbie->ipsacq_linklock = &bucket->iacqf_lock; + newbie->ipsacq_next = bucket->iacqf_ipsacq; + newbie->ipsacq_ptpn = &bucket->iacqf_ipsacq; + if (newbie->ipsacq_next != NULL) + newbie->ipsacq_next->ipsacq_ptpn = &newbie->ipsacq_next; - if (forever) { - *listp = NULL; - kmem_free(list, numentries * sizeof (*list)); + bucket->iacqf_ipsacq = newbie; + mutex_init(&newbie->ipsacq_lock, NULL, MUTEX_DEFAULT, NULL); + mutex_enter(&newbie->ipsacq_lock); } -} -/* - * Create an algorithm descriptor for an extended ACQUIRE. Filter crypto - * framework's view of reality vs. IPsec's. EF's wins, BTW. - */ -static uint8_t * -sadb_new_algdesc(uint8_t *start, uint8_t *limit, - sadb_x_ecomb_t *ecomb, uint8_t satype, uint8_t algtype, - uint8_t alg, uint16_t minbits, uint16_t maxbits, ipsec_stack_t *ipss) -{ - uint8_t *cur = start; - ipsec_alginfo_t *algp; - sadb_x_algdesc_t *algdesc = (sadb_x_algdesc_t *)cur; + /* + * XXX MLS does it actually help us to drop the bucket lock here? + * we have inserted a half-built, locked acquire record into the + * bucket. any competing thread will now be able to lock the bucket + * to scan it, but will immediately pile up on the new acquire + * record's lock; I don't think we gain anything here other than to + * disperse blame for lock contention. + * + * we might be able to dispense with acquire record locks entirely.. + * just use the bucket locks.. + */ - cur += sizeof (*algdesc); - if (cur >= limit) - return (NULL); + mutex_exit(&bucket->iacqf_lock); - ecomb->sadb_x_ecomb_numalgs++; + /* + * This assert looks silly for now, but we may need to enter newbie's + * mutex during a search. + */ + ASSERT(MUTEX_HELD(&newbie->ipsacq_lock)); /* - * Normalize vs. crypto framework's limits. This way, you can specify - * a stronger policy, and when the framework loads a stronger version, - * you can just keep plowing w/o rewhacking your SPD. + * Make the ip_xmit_attr_t into something we can queue. + * If no memory it frees datamp. */ - rw_enter(&ipss->ipsec_alg_lock, RW_READER); - algp = ipss->ipsec_alglists[(algtype == SADB_X_ALGTYPE_AUTH) ? - IPSEC_ALG_AUTH : IPSEC_ALG_ENCR][alg]; - if (algp == NULL) { - rw_exit(&ipss->ipsec_alg_lock); - return (NULL); /* Algorithm doesn't exist. Fail gracefully. */ - } - if (minbits < algp->alg_ef_minbits) - minbits = algp->alg_ef_minbits; - if (maxbits > algp->alg_ef_maxbits) - maxbits = algp->alg_ef_maxbits; - rw_exit(&ipss->ipsec_alg_lock); + asyncmp = ip_xmit_attr_to_mblk(ixa); + if (asyncmp != NULL) + linkb(asyncmp, datamp); - algdesc->sadb_x_algdesc_reserved = SADB_8TO1(algp->alg_saltlen); - algdesc->sadb_x_algdesc_satype = satype; - algdesc->sadb_x_algdesc_algtype = algtype; - algdesc->sadb_x_algdesc_alg = alg; - algdesc->sadb_x_algdesc_minbits = minbits; - algdesc->sadb_x_algdesc_maxbits = maxbits; + /* Queue up packet. Use b_next. */ - return (cur); -} + if (asyncmp == NULL) { + /* Statistics for allocation failure */ + if (ixa->ixa_flags & IXAF_IS_IPV4) { + BUMP_MIB(&ixa->ixa_ipst->ips_ip_mib, + ipIfStatsOutDiscards); + } else { + BUMP_MIB(&ixa->ixa_ipst->ips_ip6_mib, + ipIfStatsOutDiscards); + } + ip_drop_output("No memory for asyncmp", datamp, NULL); + freemsg(datamp); + /* + * The acquire record will be freed quickly if it's new + * (ipsacq_expire == 0), and will proceed as if no packet + * showed up if not. + */ + mutex_exit(&newbie->ipsacq_lock); + return; + } else if (newbie->ipsacq_numpackets == 0) { + /* First one. */ + newbie->ipsacq_mp = asyncmp; + newbie->ipsacq_numpackets = 1; + newbie->ipsacq_expire = gethrestime_sec(); + /* + * Extended ACQUIRE with both AH+ESP will use ESP's timeout + * value. + */ + newbie->ipsacq_expire += *spp->s_acquire_timeout; + newbie->ipsacq_seq = seq; + newbie->ipsacq_addrfam = af; -/* - * Convert the given ipsec_action_t into an ecomb starting at *ecomb - * which must fit before *limit - * - * return NULL if we ran out of room or a pointer to the end of the ecomb. - */ -static uint8_t * -sadb_action_to_ecomb(uint8_t *start, uint8_t *limit, ipsec_action_t *act, - netstack_t *ns) -{ - uint8_t *cur = start; - sadb_x_ecomb_t *ecomb = (sadb_x_ecomb_t *)cur; - ipsec_prot_t *ipp; - ipsec_stack_t *ipss = ns->netstack_ipsec; + newbie->ipsacq_srcport = ixa->ixa_ipsec_src_port; + newbie->ipsacq_dstport = ixa->ixa_ipsec_dst_port; + newbie->ipsacq_icmp_type = ixa->ixa_ipsec_icmp_type; + newbie->ipsacq_icmp_code = ixa->ixa_ipsec_icmp_code; + if (tunnel_mode) { + newbie->ipsacq_inneraddrfam = ixa->ixa_ipsec_inaf; + newbie->ipsacq_proto = ixa->ixa_ipsec_inaf == AF_INET6 ? + IPPROTO_IPV6 : IPPROTO_ENCAP; + newbie->ipsacq_innersrcpfx = ixa->ixa_ipsec_insrcpfx; + newbie->ipsacq_innerdstpfx = ixa->ixa_ipsec_indstpfx; + IPSA_COPY_ADDR(newbie->ipsacq_innersrc, + ixa->ixa_ipsec_insrc, ixa->ixa_ipsec_inaf); + IPSA_COPY_ADDR(newbie->ipsacq_innerdst, + ixa->ixa_ipsec_indst, ixa->ixa_ipsec_inaf); + } else { + newbie->ipsacq_proto = ixa->ixa_ipsec_proto; + } + newbie->ipsacq_unique_id = unique_id; - cur += sizeof (*ecomb); - if (cur >= limit) - return (NULL); + if (tsl != NULL) { + label_hold(tsl); + newbie->ipsacq_tsl = tsl; + } + } else { + /* Scan to the end of the list & insert. */ + mblk_t *lastone = newbie->ipsacq_mp; - ASSERT(act->ipa_act.ipa_type == IPSEC_ACT_APPLY); + while (lastone->b_next != NULL) + lastone = lastone->b_next; + lastone->b_next = asyncmp; + if (newbie->ipsacq_numpackets++ == ipsacq_maxpackets) { + newbie->ipsacq_numpackets = ipsacq_maxpackets; + lastone = newbie->ipsacq_mp; + newbie->ipsacq_mp = lastone->b_next; + lastone->b_next = NULL; - ipp = &act->ipa_act.ipa_apply; + /* Freeing the async message */ + lastone = ip_xmit_attr_free_mblk(lastone); + ip_drop_packet(lastone, B_FALSE, NULL, + DROPPER(ipss, ipds_sadb_acquire_toofull), + &ipss->ipsec_sadb_dropper); + } else { + IP_ACQUIRE_STAT(ipss, qhiwater, + newbie->ipsacq_numpackets); + } + } - ecomb->sadb_x_ecomb_numalgs = 0; - ecomb->sadb_x_ecomb_reserved = 0; - ecomb->sadb_x_ecomb_reserved2 = 0; /* - * No limits on allocations, since we really don't support that - * concept currently. + * Reset addresses. Set them to the most recently added mblk chain, + * so that the address pointers in the acquire record will point + * at an mblk still attached to the acquire list. */ - ecomb->sadb_x_ecomb_soft_allocations = 0; - ecomb->sadb_x_ecomb_hard_allocations = 0; + + newbie->ipsacq_srcaddr = src; + newbie->ipsacq_dstaddr = dst; /* - * XXX TBD: Policy or global parameters will eventually be - * able to fill in some of these. + * If the acquire record has more than one queued packet, we've + * already sent an ACQUIRE, and don't need to repeat ourself. */ - ecomb->sadb_x_ecomb_flags = 0; - ecomb->sadb_x_ecomb_soft_bytes = 0; - ecomb->sadb_x_ecomb_hard_bytes = 0; - ecomb->sadb_x_ecomb_soft_addtime = 0; - ecomb->sadb_x_ecomb_hard_addtime = 0; - ecomb->sadb_x_ecomb_soft_usetime = 0; - ecomb->sadb_x_ecomb_hard_usetime = 0; - - if (ipp->ipp_use_ah) { - cur = sadb_new_algdesc(cur, limit, ecomb, - SADB_SATYPE_AH, SADB_X_ALGTYPE_AUTH, ipp->ipp_auth_alg, - ipp->ipp_ah_minbits, ipp->ipp_ah_maxbits, ipss); - if (cur == NULL) - return (NULL); - ipsecah_fill_defs(ecomb, ns); + if (newbie->ipsacq_seq != seq || newbie->ipsacq_numpackets > 1) { + /* I have an acquire outstanding already! */ + mutex_exit(&newbie->ipsacq_lock); + return; } - if (ipp->ipp_use_esp) { - if (ipp->ipp_use_espa) { - cur = sadb_new_algdesc(cur, limit, ecomb, - SADB_SATYPE_ESP, SADB_X_ALGTYPE_AUTH, - ipp->ipp_esp_auth_alg, - ipp->ipp_espa_minbits, - ipp->ipp_espa_maxbits, ipss); - if (cur == NULL) - return (NULL); - } - - cur = sadb_new_algdesc(cur, limit, ecomb, - SADB_SATYPE_ESP, SADB_X_ALGTYPE_CRYPT, - ipp->ipp_encr_alg, - ipp->ipp_espe_minbits, - ipp->ipp_espe_maxbits, ipss); - if (cur == NULL) - return (NULL); - /* Fill in lifetimes if and only if AH didn't already... */ - if (!ipp->ipp_use_ah) - ipsecesp_fill_defs(ecomb, ns); + if (need_esp) { + ESP_BUMP_STAT(espstack, acquire_requests); + q = espstack->esp_pfkey_q; + } else { + /* + * Two cases get us here: + * 1.) AH-only policy. + * + * 2.) A continuation of an AH+ESP policy, and this is the + * post-ESP, AH-needs-to-send-a-regular-ACQUIRE case. + * (i.e. called from esp_do_outbound_ah().) + */ + AH_BUMP_STAT(ahstack, acquire_requests); + q = ahstack->ah_pfkey_q; } - return (cur); -} - -#include /* XXX should not need this */ - -/* - * From a cred_t, construct a sensitivity label extension - * - * We send up a fixed-size sensitivity label bitmap, and are perhaps - * overly chummy with the underlying data structures here. - */ - -/* ARGSUSED */ -int -sadb_sens_len_from_label(ts_label_t *tsl) -{ - int baselen = sizeof (sadb_sens_t) + _C_LEN * 4; - return (roundup(baselen, sizeof (uint64_t))); -} - -void -sadb_sens_from_label(sadb_sens_t *sens, int exttype, ts_label_t *tsl, - int senslen) -{ - uint8_t *bitmap; - bslabel_t *sl; + /* + * Get selectors and other policy-expression bits needed for an + * ACQUIRE. + */ + bzero(&sel, sizeof (sel)); + sel.ips_isv4 = (ixa->ixa_flags & IXAF_IS_IPV4) != 0; + if (tunnel_mode) { + sel.ips_protocol = (ixa->ixa_ipsec_inaf == AF_INET) ? + IPPROTO_ENCAP : IPPROTO_IPV6; + } else { + sel.ips_protocol = ixa->ixa_ipsec_proto; + sel.ips_local_port = ixa->ixa_ipsec_src_port; + sel.ips_remote_port = ixa->ixa_ipsec_dst_port; + } + sel.ips_icmp_type = ixa->ixa_ipsec_icmp_type; + sel.ips_icmp_code = ixa->ixa_ipsec_icmp_code; + sel.ips_is_icmp_inv_acq = 0; + if (af == AF_INET) { + sel.ips_local_addr_v4 = ipha->ipha_src; + sel.ips_remote_addr_v4 = ipha->ipha_dst; + } else { + sel.ips_local_addr_v6 = ip6h->ip6_src; + sel.ips_remote_addr_v6 = ip6h->ip6_dst; + } - /* LINTED */ - ASSERT((_C_LEN & 1) == 0); - ASSERT((senslen & 7) == 0); - sl = label2bslabel(tsl); + /* + * 1. Generate addresses, kmc, and sensitivity. These are "common" + * and should be an mblk pointed to by common. TBD -- eventually it + * will include triggering packet contents as more address extensions. + * + * 2. Generate ACQUIRE & KEYSOCK_OUT and single-protocol proposal. + * These are "regular" and "prop". String regular->b_cont->b_cont = + * common, common->b_cont = prop. + * + * 3. If extended register got turned on, generate EXT_ACQUIRE & + * KEYSOCK_OUT and multi-protocol eprop. These are "extended" and + * "eprop". String extended->b_cont->b_cont = dupb(common) and + * extended->b_cont->b_cont->b_cont = prop. + * + * 4. Deliver: putnext(q, regular) and if there, putnext(q, extended). + */ - sens->sadb_sens_exttype = exttype; - sens->sadb_sens_len = SADB_8TO64(senslen); + regular = extended = prop = eprop = NULL; - sens->sadb_sens_dpd = tsl->tsl_doi; - sens->sadb_sens_sens_level = LCLASS(sl); - sens->sadb_sens_integ_level = 0; /* TBD */ - sens->sadb_sens_sens_len = _C_LEN >> 1; - sens->sadb_sens_integ_len = 0; /* TBD */ - sens->sadb_x_sens_flags = 0; + common = sadb_acquire_msg_common(&sel, pp, ap, tunnel_mode, tsl, NULL); + if (common == NULL) + goto bail; - bitmap = (uint8_t *)(sens + 1); - bcopy(&(((_bslabel_impl_t *)sl)->compartments), bitmap, _C_LEN * 4); -} + regular = sadb_acquire_msg_base(0, (need_esp ? + SADB_SATYPE_ESP : SADB_SATYPE_AH), newbie->ipsacq_seq, 0); + if (regular == NULL) + goto bail; -static sadb_sens_t * -sadb_make_sens_ext(ts_label_t *tsl, int *len) -{ - /* XXX allocation failure? */ - int sens_len = sadb_sens_len_from_label(tsl); + /* + * Pardon the boolean cleverness. At least one of need_* must be true. + * If they are equal, it's an AH & ESP policy and ESP needs to go + * first. If they aren't, just check the contents of need_esp. + */ + prop = sadb_acquire_prop(ap, ns, need_esp); + if (prop == NULL) + goto bail; - sadb_sens_t *sens = kmem_alloc(sens_len, KM_SLEEP); + /* Link the parts together. */ + regular->b_cont->b_cont = common; + common->b_cont = prop; + /* + * Prop is now linked, so don't freemsg() it if the extended + * construction goes off the rails. + */ + prop = NULL; - sadb_sens_from_label(sens, SADB_EXT_SENSITIVITY, tsl, sens_len); + ((sadb_msg_t *)(regular->b_cont->b_rptr))->sadb_msg_len = + SADB_8TO64(msgsize(regular->b_cont)); - *len = sens_len; + /* + * If we need an extended ACQUIRE, build it here. + */ + if (keysock_extended_reg(ns)) { + /* NOTE: "common" still points to what we need. */ + extended = sadb_acquire_msg_base(0, 0, newbie->ipsacq_seq, 0); + if (extended == NULL) { + common = NULL; + goto bail; + } - return (sens); -} + extended->b_cont->b_cont = dupb(common); + common = NULL; + if (extended->b_cont->b_cont == NULL) + goto bail; -/* - * Okay, how do we report errors/invalid labels from this? - * With a special designated "not a label" cred_t ? - */ -/* ARGSUSED */ -ts_label_t * -sadb_label_from_sens(sadb_sens_t *sens, uint64_t *bitmap) -{ - int bitmap_len = SADB_64TO8(sens->sadb_sens_sens_len); - bslabel_t sl; - ts_label_t *tsl; + eprop = sadb_acquire_extended_prop(ap, ns); + if (eprop == NULL) + goto bail; + extended->b_cont->b_cont->b_cont = eprop; - if (sens->sadb_sens_integ_level != 0) - return (NULL); - if (sens->sadb_sens_integ_len != 0) - return (NULL); - if (bitmap_len > _C_LEN * 4) - return (NULL); + ((sadb_msg_t *)(extended->b_cont->b_rptr))->sadb_msg_len = + SADB_8TO64(msgsize(extended->b_cont)); + } - bsllow(&sl); - LCLASS_SET((_bslabel_impl_t *)&sl, sens->sadb_sens_sens_level); - bcopy(bitmap, &((_bslabel_impl_t *)&sl)->compartments, - bitmap_len); + /* So we don't hold a lock across putnext()... */ + mutex_exit(&newbie->ipsacq_lock); - tsl = labelalloc(&sl, sens->sadb_sens_dpd, KM_NOSLEEP); - if (tsl == NULL) - return (NULL); + if (extended != NULL) + putnext(q, extended); + ASSERT(regular != NULL); + putnext(q, regular); + return; - if (sens->sadb_x_sens_flags & SADB_X_SENS_UNLABELED) - tsl->tsl_flags |= TSLF_UNLABELED; - return (tsl); +bail: + /* Make this acquire record go away quickly... */ + newbie->ipsacq_expire = 0; + /* Exploit freemsg(NULL) being legal for fun & profit. */ + freemsg(common); + freemsg(prop); + freemsg(extended); + freemsg(regular); + mutex_exit(&newbie->ipsacq_lock); } -/* End XXX label-library-leakage */ - /* - * Construct an extended ACQUIRE message based on a selector and the resulting - * IPsec action. - * - * NOTE: This is used by both inverse ACQUIRE and actual ACQUIRE - * generation. As a consequence, expect this function to evolve - * rapidly. + * Unlink and free an acquire record. */ -static mblk_t * -sadb_extended_acquire(ipsec_selector_t *sel, ipsec_policy_t *pol, - ipsec_action_t *act, boolean_t tunnel_mode, uint32_t seq, uint32_t pid, - sadb_sens_t *sens, netstack_t *ns) +void +sadb_destroy_acquire(ipsacq_t *acqrec, netstack_t *ns) { - mblk_t *mp; - sadb_msg_t *samsg; - uint8_t *start, *cur, *end; - uint32_t *saddrptr, *daddrptr; - sa_family_t af; - sadb_prop_t *eprop; - ipsec_action_t *ap, *an; - ipsec_selkey_t *ipsl; - uint8_t proto, pfxlen; - uint16_t lport, rport; - uint32_t kmp, kmc; + mblk_t *mp; + ipsec_stack_t *ipss = ns->netstack_ipsec; - /* - * Find the action we want sooner rather than later.. - */ - an = NULL; - if (pol == NULL) { - ap = act; - } else { - ap = pol->ipsp_act; + ASSERT(MUTEX_HELD(acqrec->ipsacq_linklock)); - if (ap != NULL) - an = ap->ipa_next; + if (acqrec->ipsacq_policy != NULL) { + IPPOL_REFRELE(acqrec->ipsacq_policy); + } + if (acqrec->ipsacq_act != NULL) { + IPACT_REFRELE(acqrec->ipsacq_act); } - /* - * Just take a swag for the allocation for now. We can always - * alter it later. - */ -#define SADB_EXTENDED_ACQUIRE_SIZE 4096 - mp = allocb(SADB_EXTENDED_ACQUIRE_SIZE, BPRI_HI); - if (mp == NULL) - return (NULL); - - start = mp->b_rptr; - end = start + SADB_EXTENDED_ACQUIRE_SIZE; - - cur = start; - - samsg = (sadb_msg_t *)cur; - cur += sizeof (*samsg); + /* Unlink */ + *(acqrec->ipsacq_ptpn) = acqrec->ipsacq_next; + if (acqrec->ipsacq_next != NULL) + acqrec->ipsacq_next->ipsacq_ptpn = acqrec->ipsacq_ptpn; - samsg->sadb_msg_version = PF_KEY_V2; - samsg->sadb_msg_type = SADB_ACQUIRE; - samsg->sadb_msg_errno = 0; - samsg->sadb_msg_reserved = 0; - samsg->sadb_msg_satype = 0; - samsg->sadb_msg_seq = seq; - samsg->sadb_msg_pid = pid; + if (acqrec->ipsacq_tsl != NULL) { + label_rele(acqrec->ipsacq_tsl); + acqrec->ipsacq_tsl = NULL; + } - if (tunnel_mode) { - /* - * Form inner address extensions based NOT on the inner - * selectors (i.e. the packet data), but on the policy's - * selector key (i.e. the policy's selector information). - * - * NOTE: The position of IPv4 and IPv6 addresses is the - * same in ipsec_selkey_t (unless the compiler does very - * strange things with unions, consult your local C language - * lawyer for details). - */ - ASSERT(pol != NULL); + /* + * Free hanging mp's. + * + * XXX Instead of freemsg(), perhaps use IPSEC_REQ_FAILED. + */ - ipsl = &(pol->ipsp_sel->ipsl_key); - if (ipsl->ipsl_valid & IPSL_IPV4) { - af = AF_INET; - ASSERT(sel->ips_protocol == IPPROTO_ENCAP); - ASSERT(!(ipsl->ipsl_valid & IPSL_IPV6)); - } else { - af = AF_INET6; - ASSERT(sel->ips_protocol == IPPROTO_IPV6); - ASSERT(ipsl->ipsl_valid & IPSL_IPV6); - } + mutex_enter(&acqrec->ipsacq_lock); + while (acqrec->ipsacq_mp != NULL) { + mp = acqrec->ipsacq_mp; + acqrec->ipsacq_mp = mp->b_next; + mp->b_next = NULL; + /* Freeing the async message */ + mp = ip_xmit_attr_free_mblk(mp); + ip_drop_packet(mp, B_FALSE, NULL, + DROPPER(ipss, ipds_sadb_acquire_timeout), + &ipss->ipsec_sadb_dropper); + } + mutex_exit(&acqrec->ipsacq_lock); - if (ipsl->ipsl_valid & IPSL_LOCAL_ADDR) { - saddrptr = (uint32_t *)(&ipsl->ipsl_local); - pfxlen = ipsl->ipsl_local_pfxlen; - } else { - saddrptr = (uint32_t *)(&ipv6_all_zeros); - pfxlen = 0; - } - /* XXX What about ICMP type/code? */ - lport = (ipsl->ipsl_valid & IPSL_LOCAL_PORT) ? - ipsl->ipsl_lport : 0; - proto = (ipsl->ipsl_valid & IPSL_PROTOCOL) ? - ipsl->ipsl_proto : 0; + /* Free */ + mutex_destroy(&acqrec->ipsacq_lock); + kmem_free(acqrec, sizeof (*acqrec)); +} - cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_SRC, - af, saddrptr, lport, proto, pfxlen); - if (cur == NULL) { - freeb(mp); - return (NULL); - } +/* + * Destroy an acquire list fanout. + */ +static void +sadb_destroy_acqlist(iacqf_t **listp, uint_t numentries, boolean_t forever, + netstack_t *ns) +{ + int i; + iacqf_t *list = *listp; - if (ipsl->ipsl_valid & IPSL_REMOTE_ADDR) { - daddrptr = (uint32_t *)(&ipsl->ipsl_remote); - pfxlen = ipsl->ipsl_remote_pfxlen; - } else { - daddrptr = (uint32_t *)(&ipv6_all_zeros); - pfxlen = 0; - } - /* XXX What about ICMP type/code? */ - rport = (ipsl->ipsl_valid & IPSL_REMOTE_PORT) ? - ipsl->ipsl_rport : 0; + if (list == NULL) + return; - cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_DST, - af, daddrptr, rport, proto, pfxlen); - if (cur == NULL) { - freeb(mp); - return (NULL); - } - /* - * TODO - if we go to 3408's dream of transport mode IP-in-IP - * _with_ inner-packet address selectors, we'll need to further - * distinguish tunnel mode here. For now, having inner - * addresses and/or ports is sufficient. - * - * Meanwhile, whack proto/ports to reflect IP-in-IP for the - * outer addresses. - */ - proto = sel->ips_protocol; /* Either _ENCAP or _IPV6 */ - lport = rport = 0; - } else if ((ap != NULL) && (!ap->ipa_want_unique)) { - proto = 0; - lport = 0; - rport = 0; - if (pol != NULL) { - ipsl = &(pol->ipsp_sel->ipsl_key); - if (ipsl->ipsl_valid & IPSL_PROTOCOL) - proto = ipsl->ipsl_proto; - if (ipsl->ipsl_valid & IPSL_REMOTE_PORT) - rport = ipsl->ipsl_rport; - if (ipsl->ipsl_valid & IPSL_LOCAL_PORT) - lport = ipsl->ipsl_lport; - } - } else { - proto = sel->ips_protocol; - lport = sel->ips_local_port; - rport = sel->ips_remote_port; + for (i = 0; i < numentries; i++) { + mutex_enter(&(list[i].iacqf_lock)); + while (list[i].iacqf_ipsacq != NULL) + sadb_destroy_acquire(list[i].iacqf_ipsacq, ns); + mutex_exit(&(list[i].iacqf_lock)); + if (forever) + mutex_destroy(&(list[i].iacqf_lock)); } - af = sel->ips_isv4 ? AF_INET : AF_INET6; - - /* - * NOTE: The position of IPv4 and IPv6 addresses is the same in - * ipsec_selector_t. - */ - cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_SRC, af, - (uint32_t *)(&sel->ips_local_addr_v6), lport, proto, 0); - - if (cur == NULL) { - freeb(mp); - return (NULL); + if (forever) { + *listp = NULL; + kmem_free(list, numentries * sizeof (*list)); } +} - cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_DST, af, - (uint32_t *)(&sel->ips_remote_addr_v6), rport, proto, 0); +/* + * Create an algorithm descriptor for an extended ACQUIRE. Filter crypto + * framework's view of reality vs. IPsec's. EF's wins, BTW. + */ +static uint8_t * +sadb_new_algdesc(uint8_t *start, uint8_t *limit, + sadb_x_ecomb_t *ecomb, uint8_t satype, uint8_t algtype, + uint8_t alg, uint16_t minbits, uint16_t maxbits, ipsec_stack_t *ipss) +{ + uint8_t *cur = start; + ipsec_alginfo_t *algp; + sadb_x_algdesc_t *algdesc = (sadb_x_algdesc_t *)cur; - if (cur == NULL) { - freeb(mp); + cur += sizeof (*algdesc); + if (cur >= limit) return (NULL); - } - - if (sens != NULL) { - uint8_t *sensext = cur; - int senslen = SADB_64TO8(sens->sadb_sens_len); - cur += senslen; - if (cur > end) { - freeb(mp); - return (NULL); - } - bcopy(sens, sensext, senslen); - } + ecomb->sadb_x_ecomb_numalgs++; /* - * This section will change a lot as policy evolves. - * For now, it'll be relatively simple. + * Normalize vs. crypto framework's limits. This way, you can specify + * a stronger policy, and when the framework loads a stronger version, + * you can just keep plowing w/o rewhacking your SPD. */ - eprop = (sadb_prop_t *)cur; - cur += sizeof (*eprop); - if (cur > end) { - /* no space left */ - freeb(mp); - return (NULL); + rw_enter(&ipss->ipsec_alg_lock, RW_READER); + algp = ipss->ipsec_alglists[(algtype == SADB_X_ALGTYPE_AUTH) ? + IPSEC_ALG_AUTH : IPSEC_ALG_ENCR][alg]; + if (algp == NULL) { + rw_exit(&ipss->ipsec_alg_lock); + return (NULL); /* Algorithm doesn't exist. Fail gracefully. */ } + if (minbits < algp->alg_ef_minbits) + minbits = algp->alg_ef_minbits; + if (maxbits > algp->alg_ef_maxbits) + maxbits = algp->alg_ef_maxbits; + rw_exit(&ipss->ipsec_alg_lock); - eprop->sadb_prop_exttype = SADB_X_EXT_EPROP; - eprop->sadb_x_prop_ereserved = 0; - eprop->sadb_x_prop_numecombs = 0; - eprop->sadb_prop_replay = 32; /* default */ + algdesc->sadb_x_algdesc_reserved = SADB_8TO1(algp->alg_saltlen); + algdesc->sadb_x_algdesc_satype = satype; + algdesc->sadb_x_algdesc_algtype = algtype; + algdesc->sadb_x_algdesc_alg = alg; + algdesc->sadb_x_algdesc_minbits = minbits; + algdesc->sadb_x_algdesc_maxbits = maxbits; + + return (cur); +} + +/* + * Convert the given ipsec_action_t into an ecomb starting at *ecomb + * which must fit before *limit + * + * return NULL if we ran out of room or a pointer to the end of the ecomb. + */ +static uint8_t * +sadb_action_to_ecomb(uint8_t *start, uint8_t *limit, ipsec_action_t *act, + netstack_t *ns) +{ + uint8_t *cur = start; + sadb_x_ecomb_t *ecomb = (sadb_x_ecomb_t *)cur; + ipsec_prot_t *ipp; + ipsec_stack_t *ipss = ns->netstack_ipsec; - kmc = kmp = 0; + cur += sizeof (*ecomb); + if (cur >= limit) + return (NULL); - for (; ap != NULL; ap = an) { - an = (pol != NULL) ? ap->ipa_next : NULL; + ASSERT(act->ipa_act.ipa_type == IPSEC_ACT_APPLY); - /* - * Skip non-IPsec policies - */ - if (ap->ipa_act.ipa_type != IPSEC_ACT_APPLY) - continue; + ipp = &act->ipa_act.ipa_apply; - if (ap->ipa_act.ipa_apply.ipp_km_proto) - kmp = ap->ipa_act.ipa_apply.ipp_km_proto; - if (ap->ipa_act.ipa_apply.ipp_km_cookie) - kmc = ap->ipa_act.ipa_apply.ipp_km_cookie; - if (ap->ipa_act.ipa_apply.ipp_replay_depth) { - eprop->sadb_prop_replay = - ap->ipa_act.ipa_apply.ipp_replay_depth; - } + ecomb->sadb_x_ecomb_numalgs = 0; + ecomb->sadb_x_ecomb_reserved = 0; + ecomb->sadb_x_ecomb_reserved2 = 0; + /* + * No limits on allocations, since we really don't support that + * concept currently. + */ + ecomb->sadb_x_ecomb_soft_allocations = 0; + ecomb->sadb_x_ecomb_hard_allocations = 0; - cur = sadb_action_to_ecomb(cur, end, ap, ns); - if (cur == NULL) { /* no space */ - freeb(mp); + /* + * XXX TBD: Policy or global parameters will eventually be + * able to fill in some of these. + */ + ecomb->sadb_x_ecomb_flags = 0; + ecomb->sadb_x_ecomb_soft_bytes = 0; + ecomb->sadb_x_ecomb_hard_bytes = 0; + ecomb->sadb_x_ecomb_soft_addtime = 0; + ecomb->sadb_x_ecomb_hard_addtime = 0; + ecomb->sadb_x_ecomb_soft_usetime = 0; + ecomb->sadb_x_ecomb_hard_usetime = 0; + + if (ipp->ipp_use_ah) { + cur = sadb_new_algdesc(cur, limit, ecomb, + SADB_SATYPE_AH, SADB_X_ALGTYPE_AUTH, ipp->ipp_auth_alg, + ipp->ipp_ah_minbits, ipp->ipp_ah_maxbits, ipss); + if (cur == NULL) return (NULL); - } - eprop->sadb_x_prop_numecombs++; + ipsecah_fill_defs(ecomb, ns); } - if (eprop->sadb_x_prop_numecombs == 0) { - /* - * This will happen if we fail to find a policy - * allowing for IPsec processing. - * Construct an error message. - */ - samsg->sadb_msg_len = SADB_8TO64(sizeof (*samsg)); - samsg->sadb_msg_errno = ENOENT; - samsg->sadb_x_msg_diagnostic = 0; - return (mp); - } + if (ipp->ipp_use_esp) { + if (ipp->ipp_use_espa) { + cur = sadb_new_algdesc(cur, limit, ecomb, + SADB_SATYPE_ESP, SADB_X_ALGTYPE_AUTH, + ipp->ipp_esp_auth_alg, + ipp->ipp_espa_minbits, + ipp->ipp_espa_maxbits, ipss); + if (cur == NULL) + return (NULL); + } - if ((kmp != 0) || (kmc != 0)) { - cur = sadb_make_kmc_ext(cur, end, kmp, kmc); - if (cur == NULL) { - freeb(mp); + cur = sadb_new_algdesc(cur, limit, ecomb, + SADB_SATYPE_ESP, SADB_X_ALGTYPE_CRYPT, + ipp->ipp_encr_alg, + ipp->ipp_espe_minbits, + ipp->ipp_espe_maxbits, ipss); + if (cur == NULL) return (NULL); - } + /* Fill in lifetimes if and only if AH didn't already... */ + if (!ipp->ipp_use_ah) + ipsecesp_fill_defs(ecomb, ns); } - eprop->sadb_prop_len = SADB_8TO64(cur - (uint8_t *)eprop); - samsg->sadb_msg_len = SADB_8TO64(cur - start); - mp->b_wptr = cur; - - return (mp); + return (cur); } +#include /* XXX should not need this */ + /* - * Generic setup of an RFC 2367 ACQUIRE message. Caller sets satype. + * From a cred_t, construct a sensitivity label extension * - * NOTE: This function acquires alg_lock as a side-effect if-and-only-if we - * succeed (i.e. return non-NULL). Caller MUST release it. This is to - * maximize code consolidation while preventing algorithm changes from messing - * with the callers finishing touches on the ACQUIRE itself. + * We send up a fixed-size sensitivity label bitmap, and are perhaps + * overly chummy with the underlying data structures here. */ -mblk_t * -sadb_setup_acquire(ipsacq_t *acqrec, uint8_t satype, ipsec_stack_t *ipss) -{ - uint_t allocsize; - mblk_t *pfkeymp, *msgmp; - sa_family_t af; - uint8_t *cur, *end; - sadb_msg_t *samsg; - uint16_t sport_typecode; - uint16_t dport_typecode; - uint8_t check_proto; - boolean_t tunnel_mode = (acqrec->ipsacq_inneraddrfam != 0); - ASSERT(MUTEX_HELD(&acqrec->ipsacq_lock)); +/* ARGSUSED */ +int +sadb_sens_len_from_label(ts_label_t *tsl) +{ + int baselen = sizeof (sadb_sens_t) + _C_LEN * 4; + return (roundup(baselen, sizeof (uint64_t))); +} - pfkeymp = sadb_keysock_out(0); - if (pfkeymp == NULL) - return (NULL); +void +sadb_sens_from_label(sadb_sens_t *sens, int exttype, ts_label_t *tsl, + int senslen) +{ + uint8_t *bitmap; + bslabel_t *sl; - /* - * First, allocate a basic ACQUIRE message - */ - allocsize = sizeof (sadb_msg_t) + sizeof (sadb_address_t) + - sizeof (sadb_address_t) + sizeof (sadb_prop_t); + /* LINTED */ + ASSERT((_C_LEN & 1) == 0); + ASSERT((senslen & 7) == 0); - /* Make sure there's enough to cover both AF_INET and AF_INET6. */ - allocsize += 2 * sizeof (struct sockaddr_in6); + sl = label2bslabel(tsl); - rw_enter(&ipss->ipsec_alg_lock, RW_READER); - /* NOTE: The lock is now held through to this function's return. */ - allocsize += ipss->ipsec_nalgs[IPSEC_ALG_AUTH] * - ipss->ipsec_nalgs[IPSEC_ALG_ENCR] * sizeof (sadb_comb_t); + sens->sadb_sens_exttype = exttype; + sens->sadb_sens_len = SADB_8TO64(senslen); - if (tunnel_mode) { - /* Tunnel mode! */ - allocsize += 2 * sizeof (sadb_address_t); - /* Enough to cover both AF_INET and AF_INET6. */ - allocsize += 2 * sizeof (struct sockaddr_in6); - } + sens->sadb_sens_dpd = tsl->tsl_doi; + sens->sadb_sens_sens_level = LCLASS(sl); + sens->sadb_sens_integ_level = 0; /* TBD */ + sens->sadb_sens_sens_len = _C_LEN >> 1; + sens->sadb_sens_integ_len = 0; /* TBD */ + sens->sadb_x_sens_flags = 0; - msgmp = allocb(allocsize, BPRI_HI); - if (msgmp == NULL) { - freeb(pfkeymp); - rw_exit(&ipss->ipsec_alg_lock); - return (NULL); - } + bitmap = (uint8_t *)(sens + 1); + bcopy(&(((_bslabel_impl_t *)sl)->compartments), bitmap, _C_LEN * 4); +} - pfkeymp->b_cont = msgmp; - cur = msgmp->b_rptr; - end = cur + allocsize; - samsg = (sadb_msg_t *)cur; - cur += sizeof (sadb_msg_t); +/* + * Okay, how do we report errors/invalid labels from this? + * With a special designated "not a label" cred_t ? + */ +/* ARGSUSED */ +ts_label_t * +sadb_label_from_sens(sadb_sens_t *sens, uint64_t *bitmap) +{ + int bitmap_len = SADB_64TO8(sens->sadb_sens_sens_len); + bslabel_t sl; + ts_label_t *tsl; - af = acqrec->ipsacq_addrfam; - switch (af) { - case AF_INET: - check_proto = IPPROTO_ICMP; - break; - case AF_INET6: - check_proto = IPPROTO_ICMPV6; - break; - default: - /* This should never happen unless we have kernel bugs. */ - cmn_err(CE_WARN, - "sadb_setup_acquire: corrupt ACQUIRE record.\n"); - ASSERT(0); - rw_exit(&ipss->ipsec_alg_lock); + if (sens->sadb_sens_integ_level != 0) + return (NULL); + if (sens->sadb_sens_integ_len != 0) + return (NULL); + if (bitmap_len > _C_LEN * 4) return (NULL); - } - - samsg->sadb_msg_version = PF_KEY_V2; - samsg->sadb_msg_type = SADB_ACQUIRE; - samsg->sadb_msg_satype = satype; - samsg->sadb_msg_errno = 0; - samsg->sadb_msg_pid = 0; - samsg->sadb_msg_reserved = 0; - samsg->sadb_msg_seq = acqrec->ipsacq_seq; - - ASSERT(MUTEX_HELD(&acqrec->ipsacq_lock)); - - if ((acqrec->ipsacq_proto == check_proto) || tunnel_mode) { - sport_typecode = dport_typecode = 0; - } else { - sport_typecode = acqrec->ipsacq_srcport; - dport_typecode = acqrec->ipsacq_dstport; - } - - cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_SRC, af, - acqrec->ipsacq_srcaddr, sport_typecode, acqrec->ipsacq_proto, 0); - - cur = sadb_make_addr_ext(cur, end, SADB_EXT_ADDRESS_DST, af, - acqrec->ipsacq_dstaddr, dport_typecode, acqrec->ipsacq_proto, 0); - - if (tunnel_mode) { - sport_typecode = acqrec->ipsacq_srcport; - dport_typecode = acqrec->ipsacq_dstport; - cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_SRC, - acqrec->ipsacq_inneraddrfam, acqrec->ipsacq_innersrc, - sport_typecode, acqrec->ipsacq_inner_proto, - acqrec->ipsacq_innersrcpfx); - cur = sadb_make_addr_ext(cur, end, SADB_X_EXT_ADDRESS_INNER_DST, - acqrec->ipsacq_inneraddrfam, acqrec->ipsacq_innerdst, - dport_typecode, acqrec->ipsacq_inner_proto, - acqrec->ipsacq_innerdstpfx); - } - - /* XXX Insert identity information here. */ - /* XXXMLS Insert sensitivity information here. */ + bsllow(&sl); + LCLASS_SET((_bslabel_impl_t *)&sl, sens->sadb_sens_sens_level); + bcopy(bitmap, &((_bslabel_impl_t *)&sl)->compartments, + bitmap_len); - if (cur != NULL) - samsg->sadb_msg_len = SADB_8TO64(cur - msgmp->b_rptr); - else - rw_exit(&ipss->ipsec_alg_lock); + tsl = labelalloc(&sl, sens->sadb_sens_dpd, KM_NOSLEEP); + if (tsl == NULL) + return (NULL); - return (pfkeymp); + if (sens->sadb_x_sens_flags & SADB_X_SENS_UNLABELED) + tsl->tsl_flags |= TSLF_UNLABELED; + return (tsl); } +/* End XXX label-library-leakage */ + /* * Given an SADB_GETSPI message, find an appropriately ranged SA and * allocate an SA. If there are message improprieties, return (ipsa_t *)-1. @@ -6856,14 +7078,34 @@ ipsec_construct_inverse_acquire(sadb_msg_t *samsg, sadb_ext_t *extv[], } } - /* - * Now that we have a policy entry/widget, construct an ACQUIRE - * message based on that, fix fields where appropriate, - * and return the message. - */ - retmp = sadb_extended_acquire(&sel, pp, NULL, - (itp != NULL && (itp->itp_flags & ITPF_P_TUNNEL)), - samsg->sadb_msg_seq, samsg->sadb_msg_pid, sens, ns); + ASSERT(pp != NULL); + retmp = sadb_acquire_msg_base(0, 0, samsg->sadb_msg_seq, + samsg->sadb_msg_pid); + if (retmp != NULL) { + /* Remove KEYSOCK_OUT, because caller constructs it instead. */ + mblk_t *kso = retmp; + + retmp = retmp->b_cont; + freeb(kso); + /* Append addresses... */ + retmp->b_cont = sadb_acquire_msg_common(&sel, pp, NULL, + (itp != NULL && (itp->itp_flags & ITPF_P_TUNNEL)), NULL, + sens); + if (retmp->b_cont == NULL) { + freemsg(retmp); + retmp = NULL; + } + /* And the policy result. */ + retmp->b_cont->b_cont = + sadb_acquire_extended_prop(pp->ipsp_act, ns); + if (retmp->b_cont->b_cont == NULL) { + freemsg(retmp); + retmp = NULL; + } + ((sadb_msg_t *)retmp->b_rptr)->sadb_msg_len = + SADB_8TO64(msgsize(retmp)); + } + if (pp != NULL) { IPPOL_REFRELE(pp); } diff --git a/usr/src/uts/common/inet/ip/spd.c b/usr/src/uts/common/inet/ip/spd.c index 4c51307b1311..841c34501380 100644 --- a/usr/src/uts/common/inet/ip/spd.c +++ b/usr/src/uts/common/inet/ip/spd.c @@ -23,6 +23,7 @@ * Use is subject to license terms. * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2016 by Delphix. All rights reserved. + * Copyright (c) 2017, Joyent, Inc. */ /* @@ -416,9 +417,7 @@ ipsec_stack_fini(netstackid_t stackid, void *arg) rw_enter(&ipss->ipsec_alg_lock, RW_WRITER); for (algtype = 0; algtype < IPSEC_NALGTYPES; algtype ++) { - int nalgs = ipss->ipsec_nalgs[algtype]; - - for (i = 0; i < nalgs; i++) { + for (i = 0; i < IPSEC_MAX_ALGS; i++) { if (ipss->ipsec_alglists[algtype][i] != NULL) ipsec_alg_unreg(algtype, i, ns); } @@ -4688,8 +4687,9 @@ ipsid_fini(netstack_t *ns) } /* - * Update the minimum and maximum supported key sizes for the - * specified algorithm. Must be called while holding the algorithms lock. + * Update the minimum and maximum supported key sizes for the specified + * algorithm, which is either a member of a netstack alg array or about to be, + * and therefore must be called holding ipsec_alg_lock for write. */ void ipsec_alg_fix_min_max(ipsec_alginfo_t *alg, ipsec_algtype_t alg_type, diff --git a/usr/src/uts/common/inet/ipsecah.h b/usr/src/uts/common/inet/ipsecah.h index 62f96876b8f1..62f877bb8fdc 100644 --- a/usr/src/uts/common/inet/ipsecah.h +++ b/usr/src/uts/common/inet/ipsecah.h @@ -21,6 +21,7 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved. */ #ifndef _INET_IPSECAH_H @@ -114,6 +115,21 @@ struct ipsecah_stack { }; typedef struct ipsecah_stack ipsecah_stack_t; +#define ipsecah_debug ipsecah_params[0].ipsecah_param_value +#define ipsecah_age_interval ipsecah_params[1].ipsecah_param_value +#define ipsecah_age_int_max ipsecah_params[1].ipsecah_param_max +#define ipsecah_reap_delay ipsecah_params[2].ipsecah_param_value +#define ipsecah_replay_size ipsecah_params[3].ipsecah_param_value +#define ipsecah_acquire_timeout ipsecah_params[4].ipsecah_param_value +#define ipsecah_larval_timeout ipsecah_params[5].ipsecah_param_value +#define ipsecah_default_soft_bytes ipsecah_params[6].ipsecah_param_value +#define ipsecah_default_hard_bytes ipsecah_params[7].ipsecah_param_value +#define ipsecah_default_soft_addtime ipsecah_params[8].ipsecah_param_value +#define ipsecah_default_hard_addtime ipsecah_params[9].ipsecah_param_value +#define ipsecah_default_soft_usetime ipsecah_params[10].ipsecah_param_value +#define ipsecah_default_hard_usetime ipsecah_params[11].ipsecah_param_value +#define ipsecah_log_unknown_spi ipsecah_params[12].ipsecah_param_value + #endif /* _KERNEL */ /* diff --git a/usr/src/uts/common/inet/ipsecesp.h b/usr/src/uts/common/inet/ipsecesp.h index 96e139add01b..3039caf2e6b7 100644 --- a/usr/src/uts/common/inet/ipsecesp.h +++ b/usr/src/uts/common/inet/ipsecesp.h @@ -21,6 +21,7 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved. */ #ifndef _INET_IPSECESP_H @@ -43,6 +44,52 @@ typedef struct ipsecespparam_s { char *ipsecesp_param_name; } ipsecespparam_t; +/* + * Stats. This may eventually become a full-blown SNMP MIB once that spec + * stabilizes. + */ + +typedef struct esp_kstats_s { + kstat_named_t esp_stat_num_aalgs; + kstat_named_t esp_stat_good_auth; + kstat_named_t esp_stat_bad_auth; + kstat_named_t esp_stat_bad_padding; + kstat_named_t esp_stat_replay_failures; + kstat_named_t esp_stat_replay_early_failures; + kstat_named_t esp_stat_keysock_in; + kstat_named_t esp_stat_out_requests; + kstat_named_t esp_stat_acquire_requests; + kstat_named_t esp_stat_bytes_expired; + kstat_named_t esp_stat_out_discards; + kstat_named_t esp_stat_crypto_sync; + kstat_named_t esp_stat_crypto_async; + kstat_named_t esp_stat_crypto_failures; + kstat_named_t esp_stat_num_ealgs; + kstat_named_t esp_stat_bad_decrypt; + kstat_named_t esp_stat_sa_port_renumbers; +} esp_kstats_t; + +/* + * espstack->esp_kstats is equal to espstack->esp_ksp->ks_data if + * kstat_create_netstack for espstack->esp_ksp succeeds, but when it + * fails, it will be NULL. Note this is done for all stack instances, + * so it *could* fail. hence a non-NULL checking is done for + * ESP_BUMP_STAT and ESP_DEBUMP_STAT + */ +#define ESP_BUMP_STAT(espstack, x) \ +do { \ + if (espstack->esp_kstats != NULL) \ + (espstack->esp_kstats->esp_stat_ ## x).value.ui64++; \ +_NOTE(CONSTCOND) \ +} while (0) + +#define ESP_DEBUMP_STAT(espstack, x) \ +do { \ + if (espstack->esp_kstats != NULL) \ + (espstack->esp_kstats->esp_stat_ ## x).value.ui64--; \ +_NOTE(CONSTCOND) \ +} while (0) + /* * IPSECESP stack instances */ @@ -72,7 +119,31 @@ struct ipsecesp_stack { }; typedef struct ipsecesp_stack ipsecesp_stack_t; -/* Define *this* NDD variable here because we use it outside ESP proper. */ +#define ipsecesp_debug ipsecesp_params[0].ipsecesp_param_value +#define ipsecesp_age_interval ipsecesp_params[1].ipsecesp_param_value +#define ipsecesp_age_int_max ipsecesp_params[1].ipsecesp_param_max +#define ipsecesp_reap_delay ipsecesp_params[2].ipsecesp_param_value +#define ipsecesp_replay_size ipsecesp_params[3].ipsecesp_param_value +#define ipsecesp_acquire_timeout \ + ipsecesp_params[4].ipsecesp_param_value +#define ipsecesp_larval_timeout \ + ipsecesp_params[5].ipsecesp_param_value +#define ipsecesp_default_soft_bytes \ + ipsecesp_params[6].ipsecesp_param_value +#define ipsecesp_default_hard_bytes \ + ipsecesp_params[7].ipsecesp_param_value +#define ipsecesp_default_soft_addtime \ + ipsecesp_params[8].ipsecesp_param_value +#define ipsecesp_default_hard_addtime \ + ipsecesp_params[9].ipsecesp_param_value +#define ipsecesp_default_soft_usetime \ + ipsecesp_params[10].ipsecesp_param_value +#define ipsecesp_default_hard_usetime \ + ipsecesp_params[11].ipsecesp_param_value +#define ipsecesp_log_unknown_spi \ + ipsecesp_params[12].ipsecesp_param_value +#define ipsecesp_padding_check \ + ipsecesp_params[13].ipsecesp_param_value #define ipsecesp_nat_keepalive_interval \ ipsecesp_params[14].ipsecesp_param_value diff --git a/usr/src/uts/common/inet/sadb.h b/usr/src/uts/common/inet/sadb.h index 20abd4b26cb1..3dad99c0dd4e 100644 --- a/usr/src/uts/common/inet/sadb.h +++ b/usr/src/uts/common/inet/sadb.h @@ -568,15 +568,13 @@ typedef struct sadb_s } sadb_t; /* - * A pair of SADB's (one for v4, one for v6), and related state (including - * acquire callbacks). + * A pair of SADB's (one for v4, one for v6), and related state. */ typedef struct sadbp_s { uint32_t s_satype; uint32_t *s_acquire_timeout; - void (*s_acqfn)(ipsacq_t *, mblk_t *, netstack_t *); sadb_t s_v4; sadb_t s_v6; uint32_t s_addflags; @@ -773,7 +771,6 @@ void cbc_params_init(ipsa_t *, uchar_t *, uint_t, uchar_t *, ipsa_cm_mech_t *, void sadb_destroy_acquire(ipsacq_t *, netstack_t *); struct ipsec_stack; -mblk_t *sadb_setup_acquire(ipsacq_t *, uint8_t, struct ipsec_stack *); ipsa_t *sadb_getspi(keysock_in_t *, uint32_t, int *, netstack_t *, uint_t); void sadb_in_acquire(sadb_msg_t *, sadbp_t *, queue_t *, netstack_t *); boolean_t sadb_replay_check(ipsa_t *, uint32_t); diff --git a/usr/src/uts/common/io/fibre-channel/ulp/fcip.c b/usr/src/uts/common/io/fibre-channel/ulp/fcip.c index 423452e44cb9..c09f6fb6131b 100644 --- a/usr/src/uts/common/io/fibre-channel/ulp/fcip.c +++ b/usr/src/uts/common/io/fibre-channel/ulp/fcip.c @@ -4684,7 +4684,7 @@ fcip_init_port(struct fcip *fptr) int rval = FC_SUCCESS; fcip_port_info_t *fport = fptr->fcip_port_info; static char buf[64]; - size_t tok_buf_size; + size_t tok_buf_size = 0; ASSERT(fport != NULL); diff --git a/usr/src/uts/common/io/ixgbe/ixgbe_main.c b/usr/src/uts/common/io/ixgbe/ixgbe_main.c index 6ed17caa0aa7..18f5333e4860 100644 --- a/usr/src/uts/common/io/ixgbe/ixgbe_main.c +++ b/usr/src/uts/common/io/ixgbe/ixgbe_main.c @@ -25,7 +25,7 @@ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, Joyent, Inc. All rights reserved. + * Copyright 2017, Joyent, Inc. * Copyright 2012 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2013 Saso Kiselkov. All rights reserved. * Copyright (c) 2013 OSN Online Service Nuernberg GmbH. All rights reserved. @@ -4516,7 +4516,7 @@ ixgbe_intr_tx_work(ixgbe_tx_ring_t *tx_ring) tx_ring->reschedule = B_FALSE; mac_tx_ring_update(tx_ring->ixgbe->mac_hdl, tx_ring->ring_handle); - IXGBE_DEBUG_STAT(tx_ring->stat_reschedule); + tx_ring->stat_reschedule++; } } @@ -4737,7 +4737,7 @@ ixgbe_intr_legacy(void *arg1, void *arg2) if (tx_reschedule) { tx_ring->reschedule = B_FALSE; mac_tx_ring_update(ixgbe->mac_hdl, tx_ring->ring_handle); - IXGBE_DEBUG_STAT(tx_ring->stat_reschedule); + tx_ring->stat_reschedule++; } return (result); diff --git a/usr/src/uts/common/io/ixgbe/ixgbe_rx.c b/usr/src/uts/common/io/ixgbe/ixgbe_rx.c index 4a03bf3bdd47..85ae12477a6f 100644 --- a/usr/src/uts/common/io/ixgbe/ixgbe_rx.c +++ b/usr/src/uts/common/io/ixgbe/ixgbe_rx.c @@ -25,6 +25,7 @@ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2017 Joyent, Inc. */ #include "ixgbe_sw.h" @@ -601,13 +602,13 @@ ixgbe_ring_rx(ixgbe_rx_ring_t *rx_ring, int poll_bytes) if ((status_error & IXGBE_RXDADV_ERR_FRAME_ERR_MASK) || ((!ixgbe->lro_enable) && (!(status_error & IXGBE_RXD_STAT_EOP)))) { - IXGBE_DEBUG_STAT(rx_ring->stat_frame_error); + rx_ring->stat_frame_error++; goto rx_discard; } - IXGBE_DEBUG_STAT_COND(rx_ring->stat_cksum_error, - (status_error & IXGBE_RXDADV_ERR_TCPE) || - (status_error & IXGBE_RXDADV_ERR_IPE)); + if ((status_error & IXGBE_RXDADV_ERR_TCPE) || + (status_error & IXGBE_RXDADV_ERR_IPE)) + rx_ring->stat_cksum_error++; if (ixgbe->lro_enable) { rsc_cnt = (current_rbd->wb.lower.lo_dword.data & @@ -716,7 +717,7 @@ ixgbe_ring_rx(ixgbe_rx_ring_t *rx_ring, int poll_bytes) * per interrupt. */ if (++pkt_num > ixgbe->rx_limit_per_intr) { - IXGBE_DEBUG_STAT(rx_ring->stat_exceed_pkt); + rx_ring->stat_exceed_pkt++; break; } diff --git a/usr/src/uts/common/io/ixgbe/ixgbe_stat.c b/usr/src/uts/common/io/ixgbe/ixgbe_stat.c index b5ed084e77fe..2e550a9d36a9 100644 --- a/usr/src/uts/common/io/ixgbe/ixgbe_stat.c +++ b/usr/src/uts/common/io/ixgbe/ixgbe_stat.c @@ -27,6 +27,7 @@ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2012 Nexenta Systems, Inc. All rights reserved. * Copyright 2016 OmniTI Computer Consulting, Inc. All rights reserved. + * Copyright 2017 Joyent, Inc. */ #include "ixgbe_sw.h" @@ -58,7 +59,6 @@ ixgbe_update_stats(kstat_t *ks, int rw) ixgbe_ks->reset_count.value.ui64 = ixgbe->reset_count; ixgbe_ks->lroc.value.ui64 = ixgbe->lro_pkt_count; -#ifdef IXGBE_DEBUG ixgbe_ks->rx_frame_error.value.ui64 = 0; ixgbe_ks->rx_cksum_error.value.ui64 = 0; ixgbe_ks->rx_exceed_pkt.value.ui64 = 0; @@ -88,7 +88,6 @@ ixgbe_update_stats(kstat_t *ks, int rw) ixgbe_ks->tx_reschedule.value.ui64 += ixgbe->tx_rings[i].stat_reschedule; } -#endif /* * Hardware calculated statistics. @@ -245,7 +244,6 @@ ixgbe_init_stats(ixgbe_t *ixgbe) kstat_named_init(&ixgbe_ks->reset_count, "reset_count", KSTAT_DATA_UINT64); -#ifdef IXGBE_DEBUG kstat_named_init(&ixgbe_ks->rx_frame_error, "rx_frame_error", KSTAT_DATA_UINT64); kstat_named_init(&ixgbe_ks->rx_cksum_error, "rx_cksum_error", @@ -262,7 +260,6 @@ ixgbe_init_stats(ixgbe_t *ixgbe) KSTAT_DATA_UINT64); kstat_named_init(&ixgbe_ks->tx_reschedule, "tx_reschedule", KSTAT_DATA_UINT64); -#endif kstat_named_init(&ixgbe_ks->gprc, "good_pkts_recvd", KSTAT_DATA_UINT64); diff --git a/usr/src/uts/common/io/ixgbe/ixgbe_sw.h b/usr/src/uts/common/io/ixgbe/ixgbe_sw.h index 0637643cd9f4..0486972aaf82 100644 --- a/usr/src/uts/common/io/ixgbe/ixgbe_sw.h +++ b/usr/src/uts/common/io/ixgbe/ixgbe_sw.h @@ -27,6 +27,7 @@ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013 Saso Kiselkov. All rights reserved. * Copyright 2016 OmniTI Computer Consulting, Inc. All rights reserved. + * Copyright 2017 Joyent, Inc. */ #ifndef _IXGBE_SW_H @@ -505,15 +506,16 @@ typedef struct ixgbe_tx_ring { uint32_t recycle_fail; uint32_t stall_watchdog; -#ifdef IXGBE_DEBUG - /* - * Debug statistics - */ uint32_t stat_overload; uint32_t stat_fail_no_tbd; uint32_t stat_fail_no_tcb; uint32_t stat_fail_dma_bind; uint32_t stat_reschedule; + +#ifdef IXGBE_DEBUG + /* + * Debug statistics + */ uint32_t stat_break_tbd_limit; uint32_t stat_lso_header_fail; #endif @@ -580,14 +582,10 @@ typedef struct ixgbe_rx_ring { kmutex_t rx_lock; /* Rx access lock */ -#ifdef IXGBE_DEBUG - /* - * Debug statistics - */ uint32_t stat_frame_error; uint32_t stat_cksum_error; uint32_t stat_exceed_pkt; -#endif + uint64_t stat_rbytes; uint64_t stat_ipackets; diff --git a/usr/src/uts/common/io/ixgbe/ixgbe_tx.c b/usr/src/uts/common/io/ixgbe/ixgbe_tx.c index aaa1acfb0645..95e6a3b38933 100644 --- a/usr/src/uts/common/io/ixgbe/ixgbe_tx.c +++ b/usr/src/uts/common/io/ixgbe/ixgbe_tx.c @@ -27,6 +27,7 @@ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2012 Nexenta Systems, Inc. All rights reserved. * Copyright 2016 OmniTI Computer Consulting, Inc. All rights reserved. + * Copyright 2017 Joyent, Inc. */ #include "ixgbe_sw.h" @@ -163,7 +164,7 @@ ixgbe_ring_tx(void *arg, mblk_t *mp) */ if (tx_ring->tbd_free < ixgbe->tx_overload_thresh) { tx_ring->reschedule = B_TRUE; - IXGBE_DEBUG_STAT(tx_ring->stat_overload); + tx_ring->stat_overload++; return (mp); } @@ -295,7 +296,7 @@ ixgbe_ring_tx(void *arg, mblk_t *mp) tcb = ixgbe_get_free_list(tx_ring); if (tcb == NULL) { - IXGBE_DEBUG_STAT(tx_ring->stat_fail_no_tcb); + tx_ring->stat_fail_no_tcb++; goto tx_failure; } @@ -447,7 +448,7 @@ ixgbe_ring_tx(void *arg, mblk_t *mp) tcb = ixgbe_get_free_list(tx_ring); if (tcb == NULL) { - IXGBE_DEBUG_STAT(tx_ring->stat_fail_no_tcb); + tx_ring->stat_fail_no_tcb++; goto tx_failure; } desc_num = ixgbe_tx_copy(tx_ring, tcb, pull_mp, @@ -460,7 +461,7 @@ ixgbe_ring_tx(void *arg, mblk_t *mp) tcb = ixgbe_get_free_list(tx_ring); if (tcb == NULL) { - IXGBE_DEBUG_STAT(tx_ring->stat_fail_no_tcb); + tx_ring->stat_fail_no_tcb++; goto tx_failure; } if ((ctx != NULL) && ctx->lso_flag) { @@ -500,7 +501,7 @@ ixgbe_ring_tx(void *arg, mblk_t *mp) * parallel. */ if (tx_ring->tbd_free <= (desc_total + 1)) { - IXGBE_DEBUG_STAT(tx_ring->stat_fail_no_tbd); + tx_ring->stat_fail_no_tbd++; mutex_exit(&tx_ring->tx_lock); goto tx_failure; } @@ -655,7 +656,7 @@ ixgbe_tx_bind(ixgbe_tx_ring_t *tx_ring, tx_control_block_t *tcb, mblk_t *mp, 0, &dma_cookie, &ncookies); if (status != DDI_DMA_MAPPED) { - IXGBE_DEBUG_STAT(tx_ring->stat_fail_dma_bind); + tx_ring->stat_fail_dma_bind++; return (-1); }