1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * nfs log - read buffer file and print structs in user-readable form 31 */ 32 33 #define _REENTRANT 34 35 #include <ctype.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <stddef.h> 39 #include <string.h> 40 #include <strings.h> 41 #include <time.h> 42 #include <fcntl.h> 43 #include <unistd.h> 44 #include <signal.h> 45 #include <sys/types.h> 46 #include <sys/stat.h> 47 #include <sys/param.h> 48 #include <sys/utsname.h> 49 #include <errno.h> 50 #include <time.h> 51 #include <limits.h> 52 #include <libintl.h> 53 #include <pwd.h> 54 #include <netdb.h> 55 #include <syslog.h> 56 #include <rpc/rpc.h> 57 #include <netconfig.h> 58 #include <netdir.h> 59 #include <nfs/nfs_sec.h> 60 #include <nfs/export.h> 61 #include <rpc/auth.h> 62 #include <rpc/svc.h> 63 #include <rpc/xdr.h> 64 #include <rpc/clnt.h> 65 #include <nfs/nfs.h> 66 #include <nfs/nfs_log.h> 67 #include "fhtab.h" 68 #include "nfslogd.h" 69 70 static char empty_name[4] = "-"; 71 72 static char ftype3_names[NF3FIFO + 1][20] = { 73 "\"none\"", "\"file\"", "\"dir\"", "\"blk device\"", 74 "\"chr device\"", "\"link\"", "\"socket\"", "\"fifo\"" 75 }; 76 77 #define NFSL_FTYPE3(ftype) \ 78 ((((ftype) >= 0) && ((ftype) <= NF3FIFO)) ? \ 79 ftype3_names[ftype] : empty_name) 80 81 static char createmode3_names[EXCLUSIVE + 1][20] = { 82 "\"unchecked", "\"guarded\"", "\"exclusive\"" 83 }; 84 85 #define NFSL_CREATEMODE3(createmode) \ 86 ((((createmode) >= 0) && ((createmode) <= EXCLUSIVE)) ? \ 87 createmode3_names[createmode] : empty_name) 88 89 static char auth_flavor_name[RPCSEC_GSS + 1][20] = { 90 "\"auth_null\"", "\"auth_unix\"", "\"auth_short\"", "\"auth_des\"", 91 "\"auth_kerb\"", "\"none\"", "\"rpcsec_gss\"" 92 }; 93 94 #define NFSL_AUTH_FLAVOR_PRINT(auth_flavor) \ 95 (((auth_flavor) <= RPCSEC_GSS) ? \ 96 auth_flavor_name[auth_flavor] : empty_name) 97 98 #define NFSL_ERR_CNT 31 /* Actual err numbers */ 99 100 /* 101 * Two arrays - one short ints containing err codes, the other the strings 102 * (merged codes for both v2 and v3 103 */ 104 static char nfsl_status_name[NFSL_ERR_CNT][30] = { 105 "\"ok\"", "\"perm\"", "\"noent\"", "\"io\"", 106 "\"nxio\"", "\"access\"", "\"exist\"", "\"xdev\"", 107 "\"nodev\"", "\"notdir\"", "\"isdir\"", "\"inval\"", 108 "\"fbig\"", "\"nospc\"", "\"rofs\"", "\"mlink\"", 109 "\"notsupp\"", "\"nametoolong\"", "\"notempty\"", "\"dquot\"", 110 "\"stale\"", "\"remote\"", "\"wflush\"", "\"badhandle\"", 111 "\"not_sync\"", "\"bad_cookie\"", "\"notsupp\"", "\"toosmall\"", 112 "\"serverfault\"", "\"badtype\"", "\"jukebox\"", 113 }; 114 115 static short nfsl_status[NFSL_ERR_CNT] = { 116 0, 1, 2, 5, 6, 13, 17, 18, 117 19, 20, 21, 22, 27, 28, 30, 31, 118 45, 63, 66, 69, 70, 71, 99, 10001, 119 10002, 10003, 10004, 10005, 10006, 10007, 10008 120 }; 121 122 /* list of open elf files */ 123 static struct nfsl_log_file *elf_file_list = NULL; 124 125 /* Imported functions */ 126 extern void bcopy(const void *s1, void *s2, size_t n); 127 128 /* Static functions */ 129 static void nfsl_log_file_free(struct nfsl_log_file *elfrec); 130 static void nfsl_log_file_add(struct nfsl_log_file *elfrec, 131 struct nfsl_log_file **elf_listp); 132 static struct nfsl_log_file *nfsl_log_file_find(struct nfsl_log_file *elfrec, 133 struct nfsl_log_file *elf_list); 134 static struct nfsl_log_file *nfsl_log_file_del(struct nfsl_log_file *elfrec, 135 struct nfsl_log_file **elf_listp); 136 137 static char *nfsl_get_time(time_t tt); 138 static char *nfsl_get_date(time_t tt); 139 static char *nfsl_get_date_nq(time_t tt); 140 static int nfsl_write_elfbuf(struct nfsl_log_file *elfrec); 141 static void nfsl_ipaddr_print(struct nfsl_log_file *, struct netbuf *); 142 static void nfsl_elf_record_header_print(struct nfsl_log_file *, 143 nfslog_record_header *, char *, char *, 144 struct nfsl_proc_disp *, char *); 145 static void nfsl_elf_buffer_header_print(struct nfsl_log_file *, 146 nfslog_buffer_header *); 147 static struct nfsl_proc_disp *nfsl_find_elf_dispatch( 148 nfslog_request_record *, char **); 149 static void nfsl_elf_rpc_print(struct nfsl_log_file *, 150 nfslog_request_record *, struct nfsl_proc_disp *, 151 char *, char *, char *); 152 static void nfslog_size3_print(struct nfsl_log_file *, set_size3 *); 153 154 static void nfslog_null_args(struct nfsl_log_file *, caddr_t *); 155 static void nfslog_null_res(struct nfsl_log_file *, caddr_t *); 156 157 158 /* 159 * NFS VERSION 2 160 */ 161 162 /* Functions for elf print of the arguments */ 163 static void nfslog_fhandle_print(struct nfsl_log_file *, fhandle_t *); 164 static void nfslog_diropargs_print(struct nfsl_log_file *, nfslog_diropargs *); 165 static void nfslog_setattrargs_print(struct nfsl_log_file *, 166 nfslog_setattrargs *); 167 static void nfslog_sattr_print(struct nfsl_log_file *, 168 nfslog_sattr *); 169 static void nfslog_nfsreadargs_print(struct nfsl_log_file *, 170 nfslog_nfsreadargs *); 171 static void nfslog_writeargs_print(struct nfsl_log_file *, 172 nfslog_writeargs *); 173 static void nfslog_writeresult_print(struct nfsl_log_file *, 174 nfslog_writeresult *, bool_t); 175 static void nfslog_creatargs_print(struct nfsl_log_file *, 176 nfslog_createargs *); 177 static void nfslog_rddirargs_print(struct nfsl_log_file *, nfslog_rddirargs *); 178 static void nfslog_linkargs_print(struct nfsl_log_file *, nfslog_linkargs *); 179 static void nfslog_rnmargs_print(struct nfsl_log_file *, nfslog_rnmargs *); 180 static void nfslog_symlinkargs_print(struct nfsl_log_file *, 181 nfslog_symlinkargs *); 182 183 static void nfslog_sharefsargs_print(struct nfsl_log_file *, 184 nfslog_sharefsargs *); 185 static void nfslog_getfhargs_print(struct nfsl_log_file *, 186 nfslog_getfhargs *); 187 188 /* Functions for elf print of the response */ 189 static void nfslog_nfsstat_print(struct nfsl_log_file *, enum nfsstat *, 190 bool_t); 191 static void nfslog_diropres_print(struct nfsl_log_file *, nfslog_diropres *, 192 bool_t); 193 static void nfslog_rdlnres_print(struct nfsl_log_file *, nfslog_rdlnres *, 194 bool_t); 195 static void nfslog_rdresult_print(struct nfsl_log_file *, 196 nfslog_rdresult *, bool_t); 197 static void nfslog_rddirres_print(struct nfsl_log_file *, nfslog_rddirres *, 198 bool_t); 199 200 /* 201 * NFS VERSION 3 202 */ 203 204 /* Functions for elf print of the arguments */ 205 static void nfslog_fh3_print(struct nfsl_log_file *, nfs_fh3 *); 206 static void nfslog_diropargs3_print(struct nfsl_log_file *, 207 nfslog_diropargs3 *); 208 static void nfslog_SETATTR3args_print(struct nfsl_log_file *, 209 nfslog_SETATTR3args *); 210 static void nfslog_READ3args_print(struct nfsl_log_file *, nfslog_READ3args *); 211 static void nfslog_WRITE3args_print(struct nfsl_log_file *, 212 nfslog_WRITE3args *); 213 static void nfslog_CREATE3args_print(struct nfsl_log_file *, 214 nfslog_CREATE3args *); 215 static void nfslog_MKDIR3args_print(struct nfsl_log_file *, 216 nfslog_MKDIR3args *); 217 static void nfslog_SYMLINK3args_print(struct nfsl_log_file *, 218 nfslog_SYMLINK3args *); 219 static void nfslog_MKNOD3args_print(struct nfsl_log_file *, 220 nfslog_MKNOD3args *); 221 static void nfslog_REMOVE3args_print(struct nfsl_log_file *, 222 nfslog_REMOVE3args *); 223 static void nfslog_RMDIR3args_print(struct nfsl_log_file *, 224 nfslog_RMDIR3args *); 225 static void nfslog_RENAME3args_print(struct nfsl_log_file *, 226 nfslog_RENAME3args *); 227 static void nfslog_LINK3args_print(struct nfsl_log_file *, 228 nfslog_LINK3args *); 229 static void nfslog_COMMIT3args_print(struct nfsl_log_file *, 230 nfslog_COMMIT3args *); 231 static void nfslog_READDIRPLUS3args_print(struct nfsl_log_file *, 232 nfslog_READDIRPLUS3args *); 233 234 /* Functions for elf print of the response */ 235 static void nfslog_nfsstat3_print(struct nfsl_log_file *, 236 nfsstat3 *, bool_t); 237 static void nfslog_LOOKUP3res_print(struct nfsl_log_file *, 238 nfslog_LOOKUP3res *, bool_t); 239 static void nfslog_READLINK3res_print(struct nfsl_log_file *, 240 nfslog_READLINK3res *, bool_t); 241 static void nfslog_READ3res_print(struct nfsl_log_file *, 242 nfslog_READ3res *, bool_t); 243 static void nfslog_WRITE3res_print(struct nfsl_log_file *, 244 nfslog_WRITE3res *, bool_t); 245 static void nfslog_CREATE3res_print(struct nfsl_log_file *, 246 nfslog_CREATE3res *, bool_t); 247 static void nfslog_MKDIR3res_print(struct nfsl_log_file *, 248 nfslog_MKDIR3res *, bool_t); 249 static void nfslog_SYMLINK3res_print(struct nfsl_log_file *, 250 nfslog_SYMLINK3res *, bool_t); 251 static void nfslog_MKNOD3res_print(struct nfsl_log_file *, 252 nfslog_MKNOD3res *, bool_t); 253 static void nfslog_READDIRPLUS3res_print(struct nfsl_log_file *, 254 nfslog_READDIRPLUS3res *, bool_t); 255 256 extern int debug; 257 static bool_t nfsl_print_fh = FALSE; /* print file handles? */ 258 259 #define DFLT_BUFFERSIZE 8192 260 #define DFLT_OVFSIZE 3072 /* Maximum logged or buffered size */ 261 262 static char hostname[MAXHOSTNAMELEN]; /* name of host */ 263 264 265 /* 266 * Define the actions taken per prog/vers/proc: 267 * 268 * In some cases, the nl types are the same as the nfs types and a simple 269 * bcopy should suffice. Rather that define tens of identical procedures, 270 * simply define these to bcopy. Similarly this takes care of different 271 * procs that use same parameter struct. 272 */ 273 274 static struct nfsl_proc_disp nfsl_elf_proc_v2[] = { 275 /* 276 * NFS VERSION 2 277 */ 278 279 /* RFS_NULL = 0 */ 280 {nfslog_null_args, nfslog_null_res, "\"null\""}, 281 282 /* RFS_GETATTR = 1 */ 283 {nfslog_fhandle_print, nfslog_nfsstat_print, "\"getattr\""}, 284 285 /* RFS_SETATTR = 2 */ 286 {nfslog_setattrargs_print, nfslog_nfsstat_print, "\"setattr\""}, 287 288 /* RFS_ROOT = 3 *** NO LONGER SUPPORTED *** */ 289 {nfslog_null_args, nfslog_null_res, "\"root\""}, 290 291 /* RFS_LOOKUP = 4 */ 292 {nfslog_diropargs_print, nfslog_diropres_print, "\"lookup\""}, 293 294 /* RFS_READLINK = 5 */ 295 {nfslog_fhandle_print, nfslog_rdlnres_print, "\"readlink\""}, 296 297 /* RFS_READ = 6 */ 298 {nfslog_nfsreadargs_print, nfslog_rdresult_print, "\"read\""}, 299 300 /* RFS_WRITECACHE = 7 *** NO LONGER SUPPORTED *** */ 301 {nfslog_null_args, nfslog_null_res, "\"writecache\""}, 302 303 /* RFS_WRITE = 8 */ 304 {nfslog_writeargs_print, nfslog_writeresult_print, "\"write\""}, 305 306 /* RFS_CREATE = 9 */ 307 {nfslog_creatargs_print, nfslog_diropres_print, "\"create\""}, 308 309 /* RFS_REMOVE = 10 */ 310 {nfslog_diropargs_print, nfslog_nfsstat_print, "\"remove\""}, 311 312 /* RFS_RENAME = 11 */ 313 {nfslog_rnmargs_print, nfslog_nfsstat_print, "\"rename\""}, 314 315 /* RFS_LINK = 12 */ 316 {nfslog_linkargs_print, nfslog_nfsstat_print, "\"link\""}, 317 318 /* RFS_SYMLINK = 13 */ 319 {nfslog_symlinkargs_print, nfslog_nfsstat_print, "\"symlink\""}, 320 321 /* RFS_MKDIR = 14 */ 322 {nfslog_creatargs_print, nfslog_diropres_print, "\"mkdir\""}, 323 324 /* RFS_RMDIR = 15 */ 325 {nfslog_diropargs_print, nfslog_nfsstat_print, "\"rmdir\""}, 326 327 /* RFS_READDIR = 16 */ 328 {nfslog_rddirargs_print, nfslog_rddirres_print, "\"readdir\""}, 329 330 /* RFS_STATFS = 17 */ 331 {nfslog_fhandle_print, nfslog_nfsstat_print, "\"statfs\""}, 332 }; 333 334 335 /* 336 * NFS VERSION 3 337 */ 338 339 static struct nfsl_proc_disp nfsl_elf_proc_v3[] = { 340 341 /* NFSPROC3_NULL = 0 */ 342 {nfslog_null_args, nfslog_null_res, "\"null\""}, 343 344 /* NFSPROC3_GETATTR = 1 */ 345 {nfslog_fh3_print, nfslog_nfsstat3_print, "\"getattr\""}, 346 347 /* NFSPROC3_SETATTR = 2 */ 348 {nfslog_SETATTR3args_print, nfslog_nfsstat3_print, "\"setattr\""}, 349 350 /* NFSPROC3_LOOKUP = 3 */ 351 {nfslog_diropargs3_print, nfslog_LOOKUP3res_print, "\"lookup\""}, 352 353 /* NFSPROC3_ACCESS = 4 */ 354 {nfslog_fh3_print, nfslog_nfsstat3_print, "\"access\""}, 355 356 /* NFSPROC3_READLINK = 5 */ 357 {nfslog_fh3_print, nfslog_READLINK3res_print, "\"readlink\""}, 358 359 /* NFSPROC3_READ = 6 */ 360 {nfslog_READ3args_print, nfslog_READ3res_print, "\"read\""}, 361 362 /* NFSPROC3_WRITE = 7 */ 363 {nfslog_WRITE3args_print, nfslog_WRITE3res_print, "\"write\""}, 364 365 /* NFSPROC3_CREATE = 8 */ 366 {nfslog_CREATE3args_print, nfslog_CREATE3res_print, "\"create\""}, 367 368 /* NFSPROC3_MKDIR = 9 */ 369 {nfslog_MKDIR3args_print, nfslog_MKDIR3res_print, "\"mkdir\""}, 370 371 /* NFSPROC3_SYMLINK = 10 */ 372 {nfslog_SYMLINK3args_print, nfslog_SYMLINK3res_print, "\"symlink\""}, 373 374 /* NFSPROC3_MKNOD = 11 */ 375 {nfslog_MKNOD3args_print, nfslog_MKNOD3res_print, "\"mknod\""}, 376 377 /* NFSPROC3_REMOVE = 12 */ 378 {nfslog_REMOVE3args_print, nfslog_nfsstat3_print, "\"remove\""}, 379 380 /* NFSPROC3_RMDIR = 13 */ 381 {nfslog_RMDIR3args_print, nfslog_nfsstat3_print, "\"rmdir\""}, 382 383 /* NFSPROC3_RENAME = 14 */ 384 {nfslog_RENAME3args_print, nfslog_nfsstat3_print, "\"rename\""}, 385 386 /* NFSPROC3_LINK = 15 */ 387 {nfslog_LINK3args_print, nfslog_nfsstat3_print, "\"link\""}, 388 389 /* NFSPROC3_READDIR = 16 */ 390 {nfslog_fh3_print, nfslog_nfsstat3_print, "\"readdir\""}, 391 392 /* NFSPROC3_READDIRPLUS = 17 */ 393 {nfslog_READDIRPLUS3args_print, nfslog_READDIRPLUS3res_print, 394 "\"readdirplus\""}, 395 396 /* NFSPROC3_FSSTAT = 18 */ 397 {nfslog_fh3_print, nfslog_nfsstat3_print, "\"fsstat\""}, 398 399 /* NFSPROC3_FSINFO = 19 */ 400 {nfslog_fh3_print, nfslog_nfsstat3_print, "\"fsinfo\""}, 401 402 /* NFSPROC3_PATHCONF = 20 */ 403 {nfslog_fh3_print, nfslog_nfsstat3_print, "\"pathconf\""}, 404 405 /* NFSPROC3_COMMIT = 21 */ 406 {nfslog_COMMIT3args_print, nfslog_nfsstat3_print, "\"commit\""}, 407 }; 408 409 /* 410 * NFSLOG VERSION 1 411 */ 412 413 static struct nfsl_proc_disp nfsl_log_elf_proc_v1[] = { 414 415 /* NFSLOG_NULL = 0 */ 416 {nfslog_null_args, nfslog_null_res, "\"null\""}, 417 418 /* NFSLOG_SHARE = 1 */ 419 {nfslog_sharefsargs_print, nfslog_nfsstat_print, "\"log_share\""}, 420 421 /* NFSLOG_UNSHARE = 2 */ 422 {nfslog_sharefsargs_print, nfslog_nfsstat_print, "\"log_unshare\""}, 423 424 /* NFSLOG_LOOKUP = 3 */ 425 {nfslog_diropargs3_print, nfslog_LOOKUP3res_print, "\"lookup\""}, 426 427 /* NFSLOG_GETFH = 4 */ 428 {nfslog_getfhargs_print, nfslog_nfsstat_print, "\"log_getfh\""}, 429 }; 430 431 static struct nfsl_vers_disp nfsl_elf_vers_disptable[] = { 432 {sizeof (nfsl_elf_proc_v2) / sizeof (nfsl_elf_proc_v2[0]), 433 nfsl_elf_proc_v2}, 434 {sizeof (nfsl_elf_proc_v3) / sizeof (nfsl_elf_proc_v3[0]), 435 nfsl_elf_proc_v3}, 436 }; 437 438 static struct nfsl_vers_disp nfsl_log_elf_vers_disptable[] = { 439 {sizeof (nfsl_log_elf_proc_v1) / sizeof (nfsl_log_elf_proc_v1[0]), 440 nfsl_log_elf_proc_v1}, 441 }; 442 443 static struct nfsl_prog_disp nfsl_elf_dispatch_table[] = { 444 {NFS_PROGRAM, 445 NFS_VERSMIN, 446 sizeof (nfsl_elf_vers_disptable) / 447 sizeof (nfsl_elf_vers_disptable[0]), 448 nfsl_elf_vers_disptable, "nfs"}, 449 {NFSLOG_PROGRAM, 450 NFSLOG_VERSMIN, 451 sizeof (nfsl_log_elf_vers_disptable) / 452 sizeof (nfsl_log_elf_vers_disptable[0]), 453 nfsl_log_elf_vers_disptable, "nfslog"}, 454 }; 455 456 static int nfsl_elf_dispatch_table_arglen = 457 sizeof (nfsl_elf_dispatch_table) / 458 sizeof (nfsl_elf_dispatch_table[0]); 459 460 static char * 461 nfslog_get_status(short status) 462 { 463 int low, mid, high; 464 short errstat; 465 466 /* Usually status is 0... */ 467 if (status == 0) 468 return (nfsl_status_name[0]); 469 470 low = 0; 471 high = NFSL_ERR_CNT; 472 mid = NFSL_ERR_CNT / 2; 473 /* binary search for status string */ 474 while (((errstat = nfsl_status[mid]) != status) && (low < mid) && 475 (mid < high)) { 476 if (errstat > status) { /* search bottom half */ 477 high = mid; 478 } else { /* search upper half */ 479 low = mid; 480 } 481 mid = low + ((high - low) / 2); 482 } 483 if (errstat == status) { /* found it */ 484 return (nfsl_status_name[mid]); 485 } 486 return (NULL); 487 } 488 489 /* nfsl_get_time - return string with time formatted as hh:mm:ss */ 490 static char * 491 nfsl_get_time(time_t tt) 492 { 493 static char timestr[20]; 494 static time_t lasttime; 495 struct tm tmst; 496 497 if (tt == lasttime) 498 return (timestr); 499 if (localtime_r(&tt, &tmst) == NULL) { 500 return (empty_name); 501 } 502 (void) sprintf(timestr, "%02d:%02d:%02d", 503 tmst.tm_hour, tmst.tm_min, tmst.tm_sec); 504 lasttime = tt; 505 return (timestr); 506 } 507 508 /* nfsl_get_date - return date string formatted as "yyyy-mm-dd hh:mm:ss" */ 509 static char * 510 nfsl_get_date(time_t tt) 511 { 512 static char timestr[30]; 513 static time_t lasttime; 514 struct tm tmst; 515 516 if (tt == lasttime) 517 return (timestr); 518 if (localtime_r(&tt, &tmst) == NULL) { 519 return (empty_name); 520 } 521 (void) sprintf(timestr, "\"%04d-%02d-%02d %02d:%02d:%02d\"", 522 tmst.tm_year + 1900, tmst.tm_mon + 1, tmst.tm_mday, 523 tmst.tm_hour, tmst.tm_min, tmst.tm_sec); 524 lasttime = tt; 525 return (timestr); 526 } 527 528 /* 529 * nfsl_get_date_nq - return date string formatted as yyyy-mm-dd hh:mm:ss 530 * (no quotes) 531 */ 532 static char * 533 nfsl_get_date_nq(time_t tt) 534 { 535 static char timestr[30]; 536 static time_t lasttime; 537 struct tm tmst; 538 539 if (tt == lasttime) 540 return (timestr); 541 if (localtime_r(&tt, &tmst) == NULL) { 542 return (empty_name); 543 } 544 (void) sprintf(timestr, "%04d-%02d-%02d %02d:%02d:%02d", 545 tmst.tm_year + 1900, tmst.tm_mon + 1, tmst.tm_mday, 546 tmst.tm_hour, tmst.tm_min, tmst.tm_sec); 547 return (timestr); 548 } 549 550 /* write log buffer out to file */ 551 static int 552 nfsl_write_elfbuf(struct nfsl_log_file *elfrec) 553 { 554 int rc; 555 char *elfbuf = elfrec->buf; 556 int elfbufoffset = elfrec->bufoffset; 557 558 if (debug > 1) 559 (void) printf("nfsl_write_elfbuf: bufoffset %d\n", 560 elfbufoffset); 561 if (elfbufoffset <= 0) 562 return (0); 563 elfbuf[elfbufoffset] = '\0'; 564 if ((rc = fputs(elfbuf, elfrec->fp)) < 0) { 565 syslog(LOG_ERR, gettext("Write to %s failed: %s\n"), 566 elfrec->path, strerror(errno)); 567 return (-1); 568 } 569 if (rc != elfbufoffset) { 570 syslog(LOG_ERR, gettext("Write %d bytes to %s returned %d\n"), 571 elfbufoffset, elfrec->path, rc); 572 return (-1); 573 } 574 elfrec->bufoffset = 0; 575 return (0); 576 } 577 578 /*ARGSUSED*/ 579 static void 580 nfslog_null_args(struct nfsl_log_file *elfrec, caddr_t *nfsl_args) 581 { 582 } 583 584 /*ARGSUSED*/ 585 static void 586 nfslog_null_res(struct nfsl_log_file *elfrec, caddr_t *nfsl_res) 587 { 588 } 589 590 static void 591 nfslog_fh3_print(struct nfsl_log_file *elfrec, nfs_fh3 *fh3) 592 { 593 if (!nfsl_print_fh) 594 return; 595 if (fh3->fh3_length == sizeof (fh3->fh3_u.nfs_fh3_i.fh3_i)) { 596 nfslog_fhandle_print(elfrec, &fh3->fh3_u.nfs_fh3_i.fh3_i); 597 } else { 598 nfslog_opaque_print_buf(fh3->fh3_u.data, fh3->fh3_length, 599 elfrec->buf, &elfrec->bufoffset, 600 DFLT_BUFFERSIZE + DFLT_OVFSIZE); 601 } 602 } 603 604 /* 605 * NFS VERSION 2 606 */ 607 608 609 /* Functions that elf print the arguments */ 610 611 static void 612 nfslog_fhandle_print(struct nfsl_log_file *elfrec, fhandle_t *args) 613 { 614 if (!nfsl_print_fh) 615 return; 616 nfslog_opaque_print_buf(args, sizeof (*args), 617 elfrec->buf, &elfrec->bufoffset, 618 DFLT_BUFFERSIZE + DFLT_OVFSIZE); 619 } 620 621 static void 622 nfslog_diropargs_print(struct nfsl_log_file *elfrec, nfslog_diropargs *args) 623 { 624 char *elfbuf = elfrec->buf; 625 int elfbufoffset = elfrec->bufoffset; 626 627 if (nfsl_print_fh) { 628 nfslog_fhandle_print(elfrec, &args->da_fhandle); 629 elfbufoffset = elfrec->bufoffset; 630 if (args->da_name != NULL) { 631 elfbufoffset += sprintf(&elfbuf[elfbufoffset], 632 " \"%s\"", args->da_name); 633 } else { 634 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s", 635 empty_name); 636 } 637 } 638 elfrec->bufoffset = elfbufoffset; 639 } 640 641 static void 642 nfslog_sattr_print(struct nfsl_log_file *elfrec, nfslog_sattr *args) 643 { 644 char *elfbuf = elfrec->buf; 645 int elfbufoffset = elfrec->bufoffset; 646 647 /* BEGIN CSTYLED */ 648 if (args->sa_mode != (uint32_t)-1) { 649 elfbufoffset += sprintf(&elfbuf[elfbufoffset], 650 " \"mode=0%o\"", args->sa_mode); 651 } 652 if (args->sa_uid != (uint32_t)-1) { 653 elfbufoffset += sprintf(&elfbuf[elfbufoffset], 654 " \"uid=0x%x\"", args->sa_uid); 655 } 656 if (args->sa_gid != (uint32_t)-1) { 657 elfbufoffset += sprintf(&elfbuf[elfbufoffset], 658 " \"gid=0x%x\"", args->sa_gid); 659 } 660 if (args->sa_size != (uint32_t)-1) { 661 elfbufoffset += sprintf(&elfbuf[elfbufoffset], 662 " \"size=0x%x\"", args->sa_size); 663 } 664 if (args->sa_atime.tv_sec != (uint32_t)-1) { 665 elfbufoffset += sprintf(&elfbuf[elfbufoffset], 666 " \"atime=%s\"", 667 nfsl_get_date_nq((time_t)args->sa_atime.tv_sec)); 668 } 669 if (args->sa_mtime.tv_sec != (uint32_t)-1) { 670 elfbufoffset += sprintf(&elfbuf[elfbufoffset], 671 " \"mtime=%s\"", 672 nfsl_get_date_nq((time_t)args->sa_mtime.tv_sec)); 673 } 674 /* END CSTYLED */ 675 elfrec->bufoffset = elfbufoffset; 676 } 677 678 static void 679 nfslog_setattrargs_print(struct nfsl_log_file *elfrec, nfslog_setattrargs *args) 680 { 681 nfslog_fhandle_print(elfrec, &args->saa_fh); 682 nfslog_sattr_print(elfrec, &args->saa_sa); 683 } 684 685 static void 686 nfslog_nfsreadargs_print(struct nfsl_log_file *elfrec, 687 nfslog_nfsreadargs *args) 688 { 689 char *elfbuf = elfrec->buf; 690 int elfbufoffset; 691 692 nfslog_fhandle_print(elfrec, &args->ra_fhandle); 693 elfbufoffset = elfrec->bufoffset; 694 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x", 695 args->ra_offset); 696 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x", 697 args->ra_count); 698 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x", 699 args->ra_totcount); 700 elfrec->bufoffset = elfbufoffset; 701 } 702 703 static void 704 nfslog_writeargs_print(struct nfsl_log_file *elfrec, nfslog_writeargs *args) 705 { 706 char *elfbuf = elfrec->buf; 707 int elfbufoffset = elfrec->bufoffset; 708 709 nfslog_fhandle_print(elfrec, &args->waargs_fhandle); 710 elfbufoffset = elfrec->bufoffset; 711 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x", 712 args->waargs_begoff); 713 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x", 714 args->waargs_offset); 715 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x", 716 args->waargs_totcount); 717 elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], " 0x%x", 718 args->waargs_count); 719 } 720 721 static void 722 nfslog_writeresult_print(struct nfsl_log_file *elfrec, nfslog_writeresult *res, 723 bool_t print_status) 724 { 725 char *elfbuf = elfrec->buf; 726 int elfbufoffset = elfrec->bufoffset; 727 728 if (print_status) { 729 nfslog_nfsstat_print(elfrec, &res->wr_status, print_status); 730 } else if (res->wr_status == NFS_OK) { 731 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x", 732 res->nfslog_writeresult_u.wr_size); 733 elfrec->bufoffset = elfbufoffset; 734 } 735 } 736 737 static void 738 nfslog_creatargs_print(struct nfsl_log_file *elfrec, nfslog_createargs *args) 739 { 740 nfslog_diropargs_print(elfrec, &args->ca_da); 741 nfslog_sattr_print(elfrec, &args->ca_sa); 742 } 743 744 745 static void 746 nfslog_rddirargs_print(struct nfsl_log_file *elfrec, nfslog_rddirargs *args) 747 { 748 char *elfbuf = elfrec->buf; 749 int elfbufoffset; 750 751 nfslog_fhandle_print(elfrec, &args->rda_fh); 752 elfbufoffset = elfrec->bufoffset; 753 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x", 754 args->rda_offset); 755 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x", 756 args->rda_count); 757 elfrec->bufoffset = elfbufoffset; 758 } 759 760 static void 761 nfslog_rnmargs_print(struct nfsl_log_file *elfrec, nfslog_rnmargs *args) 762 { 763 nfslog_diropargs_print(elfrec, &args->rna_from); 764 nfslog_diropargs_print(elfrec, &args->rna_to); 765 } 766 767 static void 768 nfslog_linkargs_print(struct nfsl_log_file *elfrec, nfslog_linkargs *args) 769 { 770 nfslog_fhandle_print(elfrec, &args->la_from); 771 nfslog_diropargs_print(elfrec, &args->la_to); 772 } 773 774 static void 775 nfslog_symlinkargs_print(struct nfsl_log_file *elfrec, nfslog_symlinkargs *args) 776 { 777 char *elfbuf = elfrec->buf; 778 int elfbufoffset; 779 780 nfslog_diropargs_print(elfrec, &args->sla_from); 781 elfbufoffset = elfrec->bufoffset; 782 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " \"%s\"", 783 args->sla_tnm); 784 elfrec->bufoffset = elfbufoffset; 785 nfslog_sattr_print(elfrec, &args->sla_sa); 786 } 787 788 /* 789 * SHARE/UNSHARE fs log args copy 790 */ 791 static void 792 nfslog_sharefsargs_print(struct nfsl_log_file *elfrec, 793 nfslog_sharefsargs *args) 794 { 795 unsigned int elfbufoffset; 796 char *elfbuf = elfrec->buf; 797 798 nfslog_fhandle_print(elfrec, &args->sh_fh_buf); 799 800 elfbufoffset = elfrec->bufoffset; 801 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x", 802 args->sh_flags); 803 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x", 804 args->sh_anon); 805 if (nfsl_print_fh) { 806 if (args->sh_path != NULL) { 807 elfbufoffset += sprintf(&elfbuf[elfbufoffset], 808 " \"%s\"", args->sh_path); 809 } else { 810 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s", 811 empty_name); 812 } 813 } 814 elfrec->bufoffset = elfbufoffset; 815 } 816 817 static void 818 nfslog_getfhargs_print(struct nfsl_log_file *elfrec, 819 nfslog_getfhargs *args) 820 { 821 unsigned int elfbufoffset; 822 char *elfbuf = elfrec->buf; 823 824 nfslog_fhandle_print(elfrec, &args->gfh_fh_buf); 825 826 elfbufoffset = elfrec->bufoffset; 827 if (nfsl_print_fh) { 828 if (args->gfh_path != NULL) { 829 elfbufoffset += sprintf(&elfbuf[elfbufoffset], 830 " \"%s\"", args->gfh_path); 831 } else { 832 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s", 833 empty_name); 834 } 835 } 836 elfrec->bufoffset = elfbufoffset; 837 } 838 839 static void 840 nfslog_nfsstat_print(struct nfsl_log_file *elfrec, enum nfsstat *res, 841 bool_t print_status) 842 { 843 if (print_status) { 844 char *statp = nfslog_get_status((short)(*res)); 845 846 if (statp != NULL) 847 elfrec->bufoffset += 848 sprintf(&elfrec->buf[elfrec->bufoffset], " %s", 849 statp); 850 else 851 elfrec->bufoffset += 852 sprintf(&elfrec->buf[elfrec->bufoffset], " %5d", 853 *res); 854 } 855 } 856 857 static void 858 nfslog_diropres_print(struct nfsl_log_file *elfrec, nfslog_diropres *res, 859 bool_t print_status) 860 { 861 if (print_status) { 862 nfslog_nfsstat_print(elfrec, &res->dr_status, print_status); 863 } else if (res->dr_status == NFS_OK) { 864 nfslog_fhandle_print(elfrec, 865 &res->nfslog_diropres_u.dr_ok.drok_fhandle); 866 } 867 } 868 869 static void 870 nfslog_rdlnres_print(struct nfsl_log_file *elfrec, nfslog_rdlnres *res, 871 bool_t print_status) 872 { 873 if (print_status) { 874 nfslog_nfsstat_print(elfrec, &res->rl_status, print_status); 875 } else if (res->rl_status == NFS_OK) { 876 elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], 877 " \"%s\"", res->nfslog_rdlnres_u.rl_ok); 878 } 879 } 880 881 static void 882 nfslog_rdresult_print(struct nfsl_log_file *elfrec, nfslog_rdresult *res, 883 bool_t print_status) 884 { 885 if (print_status) { 886 nfslog_nfsstat_print(elfrec, &res->r_status, print_status); 887 } else if (res->r_status == NFS_OK) { 888 elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], 889 " 0x%x", res->nfslog_rdresult_u.r_ok.filesize); 890 elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], 891 " 0x%x", res->nfslog_rdresult_u.r_ok.rrok_count); 892 } 893 } 894 895 static void 896 nfslog_rddirres_print(struct nfsl_log_file *elfrec, nfslog_rddirres *res, 897 bool_t print_status) 898 { 899 if (print_status) { 900 nfslog_nfsstat_print(elfrec, &res->rd_status, print_status); 901 } else if (res->rd_status == NFS_OK) { 902 char *elfbuf = elfrec->buf; 903 int elfbufoffset = elfrec->bufoffset; 904 905 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x", 906 res->nfslog_rddirres_u.rd_ok.rdok_offset); 907 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x", 908 res->nfslog_rddirres_u.rd_ok.rdok_size); 909 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x", 910 res->nfslog_rddirres_u.rd_ok.rdok_eof); 911 elfrec->bufoffset = elfbufoffset; 912 } 913 } 914 915 /* 916 * NFS VERSION 3 917 */ 918 919 static void 920 nfslog_diropargs3_print(struct nfsl_log_file *elfrec, 921 nfslog_diropargs3 *args) 922 { 923 if (nfsl_print_fh) { 924 nfslog_fh3_print(elfrec, &args->dir); 925 elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], 926 " \"%s\"", args->name); 927 } 928 } 929 930 static void 931 nfslog_size3_print(struct nfsl_log_file *elfrec, set_size3 *args) 932 { 933 char *elfbuf = elfrec->buf; 934 int elfbufoffset = elfrec->bufoffset; 935 936 if (args->set_it) { 937 elfbufoffset += sprintf(&elfbuf[elfbufoffset], 938 /* CSTYLED */ 939 " \"size=0x%llx\"", args->size); 940 } 941 elfrec->bufoffset = elfbufoffset; 942 } 943 944 static void 945 nfslog_SETATTR3args_print(struct nfsl_log_file *elfrec, 946 nfslog_SETATTR3args *args) 947 { 948 nfslog_fh3_print(elfrec, &args->object); 949 nfslog_size3_print(elfrec, &args->size); 950 } 951 952 static void 953 nfslog_READ3args_print(struct nfsl_log_file *elfrec, nfslog_READ3args *args) 954 { 955 nfslog_fh3_print(elfrec, &args->file); 956 elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], " 0x%llx", 957 args->offset); 958 elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], " 0x%x", 959 args->count); 960 } 961 962 static void 963 nfslog_WRITE3args_print(struct nfsl_log_file *elfrec, 964 nfslog_WRITE3args *args) 965 { 966 char *elfbuf = elfrec->buf; 967 int elfbufoffset; 968 969 nfslog_fh3_print(elfrec, &args->file); 970 elfbufoffset = elfrec->bufoffset; 971 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%llx", 972 args->offset); 973 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x", 974 args->count); 975 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x", 976 args->stable); 977 elfrec->bufoffset = elfbufoffset; 978 } 979 980 static void 981 nfslog_CREATE3args_print(struct nfsl_log_file *elfrec, 982 nfslog_CREATE3args *args) 983 { 984 nfslog_diropargs3_print(elfrec, &args->where); 985 elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], " %s", 986 NFSL_CREATEMODE3(args->how.mode)); 987 if (args->how.mode != EXCLUSIVE) { 988 nfslog_size3_print(elfrec, 989 &args->how.nfslog_createhow3_u.size); 990 } 991 } 992 993 static void 994 nfslog_MKDIR3args_print(struct nfsl_log_file *elfrec, 995 nfslog_MKDIR3args *args) 996 { 997 nfslog_diropargs3_print(elfrec, &args->where); 998 } 999 1000 static void 1001 nfslog_SYMLINK3args_print(struct nfsl_log_file *elfrec, 1002 nfslog_SYMLINK3args *args) 1003 { 1004 nfslog_diropargs3_print(elfrec, &args->where); 1005 elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], 1006 " \"%s\"", args->symlink_data); 1007 } 1008 1009 static void 1010 nfslog_MKNOD3args_print(struct nfsl_log_file *elfrec, 1011 nfslog_MKNOD3args *args) 1012 { 1013 nfslog_diropargs3_print(elfrec, &args->where); 1014 elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], " %s", 1015 NFSL_FTYPE3(args->type)); 1016 } 1017 1018 static void 1019 nfslog_REMOVE3args_print(struct nfsl_log_file *elfrec, 1020 nfslog_REMOVE3args *args) 1021 { 1022 nfslog_diropargs3_print(elfrec, &args->object); 1023 } 1024 1025 static void 1026 nfslog_RMDIR3args_print(struct nfsl_log_file *elfrec, 1027 nfslog_RMDIR3args *args) 1028 { 1029 nfslog_diropargs3_print(elfrec, &args->object); 1030 } 1031 1032 static void 1033 nfslog_RENAME3args_print(struct nfsl_log_file *elfrec, 1034 nfslog_RENAME3args *args) 1035 { 1036 nfslog_diropargs3_print(elfrec, &args->from); 1037 nfslog_diropargs3_print(elfrec, &args->to); 1038 } 1039 1040 static void 1041 nfslog_LINK3args_print(struct nfsl_log_file *elfrec, nfslog_LINK3args *args) 1042 { 1043 nfslog_fh3_print(elfrec, &args->file); 1044 nfslog_diropargs3_print(elfrec, &args->link); 1045 } 1046 1047 static void 1048 nfslog_READDIRPLUS3args_print(struct nfsl_log_file *elfrec, 1049 nfslog_READDIRPLUS3args *args) 1050 { 1051 nfslog_fh3_print(elfrec, &args->dir); 1052 elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], " 0x%x", 1053 args->dircount); 1054 elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], " 0x%x", 1055 args->maxcount); 1056 } 1057 1058 static void 1059 nfslog_COMMIT3args_print(struct nfsl_log_file *elfrec, 1060 nfslog_COMMIT3args *args) 1061 { 1062 nfslog_fh3_print(elfrec, &args->file); 1063 elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], " 0x%llx", 1064 args->offset); 1065 elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], " 0x%x", 1066 args->count); 1067 } 1068 1069 static void 1070 nfslog_nfsstat3_print(struct nfsl_log_file *elfrec, enum nfsstat3 *res, 1071 bool_t print_status) 1072 { 1073 if (print_status) { 1074 char *statp = nfslog_get_status((short)(*res)); 1075 1076 if (statp != NULL) 1077 elfrec->bufoffset += 1078 sprintf(&elfrec->buf[elfrec->bufoffset], " %s", 1079 statp); 1080 else 1081 elfrec->bufoffset += 1082 sprintf(&elfrec->buf[elfrec->bufoffset], " %5d", 1083 *res); 1084 } 1085 } 1086 1087 static void 1088 nfslog_LOOKUP3res_print(struct nfsl_log_file *elfrec, 1089 nfslog_LOOKUP3res *res, bool_t print_status) 1090 { 1091 if (print_status) { 1092 nfslog_nfsstat3_print(elfrec, &res->status, print_status); 1093 } else if (res->status == NFS3_OK) { 1094 nfslog_fh3_print(elfrec, &res->nfslog_LOOKUP3res_u.object); 1095 } 1096 } 1097 1098 static void 1099 nfslog_READLINK3res_print(struct nfsl_log_file *elfrec, 1100 nfslog_READLINK3res *res, bool_t print_status) 1101 { 1102 if (print_status) { 1103 nfslog_nfsstat3_print(elfrec, &res->status, print_status); 1104 } else if (res->status == NFS3_OK) { 1105 elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], 1106 " %s", res->nfslog_READLINK3res_u.data); 1107 } 1108 } 1109 1110 static void 1111 nfslog_READ3res_print(struct nfsl_log_file *elfrec, nfslog_READ3res *res, 1112 bool_t print_status) 1113 { 1114 if (print_status) { 1115 nfslog_nfsstat3_print(elfrec, &res->status, print_status); 1116 } else if (res->status == NFS3_OK) { 1117 char *elfbuf = elfrec->buf; 1118 int elfbufoffset = elfrec->bufoffset; 1119 1120 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%llx", 1121 res->nfslog_READ3res_u.ok.filesize); 1122 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x", 1123 res->nfslog_READ3res_u.ok.count); 1124 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x", 1125 res->nfslog_READ3res_u.ok.eof); 1126 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x", 1127 res->nfslog_READ3res_u.ok.size); 1128 elfrec->bufoffset = elfbufoffset; 1129 } 1130 } 1131 1132 static void 1133 nfslog_WRITE3res_print(struct nfsl_log_file *elfrec, nfslog_WRITE3res *res, 1134 bool_t print_status) 1135 { 1136 if (print_status) { 1137 nfslog_nfsstat3_print(elfrec, &res->status, print_status); 1138 } else if (res->status == NFS3_OK) { 1139 char *elfbuf = elfrec->buf; 1140 int elfbufoffset = elfrec->bufoffset; 1141 1142 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%llx", 1143 res->nfslog_WRITE3res_u.ok.filesize); 1144 elfbufoffset += sprintf(&elfbuf[elfbufoffset], 1145 " 0x%x", res->nfslog_WRITE3res_u.ok.count); 1146 elfbufoffset += sprintf(&elfrec->buf[elfbufoffset], 1147 " 0x%x", res->nfslog_WRITE3res_u.ok.committed); 1148 elfrec->bufoffset = elfbufoffset; 1149 } 1150 } 1151 1152 static void 1153 nfslog_CREATE3res_print(struct nfsl_log_file *elfrec, nfslog_CREATE3res *res, 1154 bool_t print_status) 1155 { 1156 if (print_status) { 1157 nfslog_nfsstat3_print(elfrec, &res->status, print_status); 1158 } else if (res->status == NFS3_OK) { 1159 if (res->nfslog_CREATE3res_u.ok.obj.handle_follows) { 1160 nfslog_fh3_print(elfrec, 1161 &res->nfslog_CREATE3res_u.ok.obj.handle); 1162 } 1163 } 1164 } 1165 1166 static void 1167 nfslog_MKDIR3res_print(struct nfsl_log_file *elfrec, nfslog_MKDIR3res *res, 1168 bool_t print_status) 1169 { 1170 if (print_status) { 1171 nfslog_nfsstat3_print(elfrec, &res->status, print_status); 1172 } else if (res->status == NFS3_OK) { 1173 if (res->nfslog_MKDIR3res_u.obj.handle_follows) { 1174 nfslog_fh3_print(elfrec, 1175 &res->nfslog_MKDIR3res_u.obj.handle); 1176 } 1177 } 1178 } 1179 1180 static void 1181 nfslog_SYMLINK3res_print(struct nfsl_log_file *elfrec, nfslog_SYMLINK3res *res, 1182 bool_t print_status) 1183 { 1184 if (print_status) { 1185 nfslog_nfsstat3_print(elfrec, &res->status, print_status); 1186 } else if (res->status == NFS3_OK) { 1187 if (res->nfslog_SYMLINK3res_u.obj.handle_follows) { 1188 nfslog_fh3_print(elfrec, 1189 &res->nfslog_SYMLINK3res_u.obj.handle); 1190 } 1191 } 1192 } 1193 1194 static void 1195 nfslog_MKNOD3res_print(struct nfsl_log_file *elfrec, nfslog_MKNOD3res *res, 1196 bool_t print_status) 1197 { 1198 if (print_status) { 1199 nfslog_nfsstat3_print(elfrec, &res->status, print_status); 1200 } else if (res->status == NFS3_OK) { 1201 if (res->nfslog_MKNOD3res_u.obj.handle_follows) { 1202 nfslog_fh3_print(elfrec, 1203 &res->nfslog_MKNOD3res_u.obj.handle); 1204 } 1205 } 1206 } 1207 1208 static void 1209 nfslog_READDIRPLUS3res_print(struct nfsl_log_file *elfrec, 1210 nfslog_READDIRPLUS3res *res, bool_t print_status) 1211 { 1212 if (print_status) { 1213 nfslog_nfsstat3_print(elfrec, &res->status, print_status); 1214 } 1215 } 1216 1217 /* 1218 * **** End of table functions for logging specific procs **** 1219 * 1220 * Hereafter are the general logging management and dispatcher. 1221 */ 1222 1223 1224 /* 1225 * nfsl_ipaddr_print - extracts sender ip address from transport struct 1226 * and prints it in legible form. 1227 */ 1228 static void 1229 nfsl_ipaddr_print(struct nfsl_log_file *elfrec, struct netbuf *ptr) 1230 { 1231 struct hostent *hp; 1232 extern char *inet_ntop(); 1233 int size, sin_family, error; 1234 char *elfbuf = elfrec->buf; 1235 char *addrp; 1236 int elfbufoffset = elfrec->bufoffset; 1237 1238 if (ptr->len == 0) { 1239 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s", 1240 empty_name); 1241 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s", 1242 empty_name); 1243 elfrec->bufoffset = elfbufoffset; 1244 return; 1245 } 1246 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " "); 1247 /* LINTED */ 1248 sin_family = ((struct sockaddr_in *)ptr->buf)->sin_family; 1249 switch (sin_family) { 1250 case (AF_INET): 1251 /* LINTED */ 1252 addrp = (char *)&((struct sockaddr_in *)ptr->buf)->sin_addr; 1253 size = sizeof (struct in_addr); 1254 break; 1255 case (AF_INET6): 1256 /* LINTED */ 1257 addrp = (char *)&((struct sockaddr_in6 *)ptr->buf)->sin6_addr; 1258 size = sizeof (struct in6_addr); 1259 break; 1260 default: 1261 /* unknown protocol: print address in hex form */ 1262 for (size = ptr->len, addrp = ptr->buf; size > 0; size--) { 1263 elfbufoffset += sprintf(&elfbuf[elfbufoffset], "%02x", 1264 *addrp); 1265 } 1266 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s", 1267 empty_name); 1268 elfrec->bufoffset = elfbufoffset; 1269 return; 1270 } 1271 if (inet_ntop(sin_family, addrp, &elfbuf[elfbufoffset], 1272 (size_t)(DFLT_BUFFERSIZE + DFLT_OVFSIZE - elfbufoffset)) 1273 == NULL) { 1274 /* Not enough space to print - should never happen */ 1275 elfbuf[elfrec->bufoffset] = '\0'; /* just in case */ 1276 return; 1277 } 1278 /* inet_ntop copied address into elfbuf, so update offset */ 1279 elfbufoffset += strlen(&elfbuf[elfbufoffset]); 1280 /* get host name and log it as well */ 1281 hp = getipnodebyaddr(addrp, size, sin_family, &error); 1282 if (hp != NULL) { 1283 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " \"%s\"", 1284 hp->h_name); 1285 } else { 1286 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s", 1287 empty_name); 1288 } 1289 elfrec->bufoffset = elfbufoffset; 1290 } 1291 1292 static void 1293 nfsl_elf_record_header_print(struct nfsl_log_file *elfrec, 1294 nfslog_record_header *lhp, char *principal_name, char *tag, 1295 struct nfsl_proc_disp *disp, char *progname) 1296 { 1297 struct passwd *pwp = NULL; 1298 char *elfbuf = elfrec->buf; 1299 int elfbufoffset = elfrec->bufoffset; 1300 1301 /* 1302 * Fields: time bytes tag rpc-program rpc-version rpc-procedure 1303 * auth-flavor s-user-name s-uid uid u-name gid net-id 1304 * c-ip c-dns s-dns status rpcarg-path <arguments> <response> 1305 */ 1306 elfbufoffset += sprintf(&elfbuf[elfbufoffset], "%s", 1307 nfsl_get_time((time_t)lhp->rh_timestamp.tv_sec)); 1308 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%x", 1309 lhp->rh_reclen); 1310 if ((tag != NULL) && (tag[0] != '\0')) { 1311 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " \"%s\"", tag); 1312 } else { 1313 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s", 1314 empty_name); 1315 } 1316 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s 0x%x %s", 1317 progname, lhp->rh_version, disp->procname); 1318 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s", 1319 NFSL_AUTH_FLAVOR_PRINT(lhp->rh_auth_flavor)); 1320 if ((principal_name != NULL) && (principal_name[0] != '\0')) { 1321 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " \"%s\"", 1322 principal_name); 1323 if ((pwp = getpwnam(principal_name)) != NULL) { 1324 elfbufoffset += sprintf(&elfbuf[elfbufoffset], 1325 " 0x%lx", pwp->pw_uid); 1326 } else { 1327 elfbufoffset += sprintf(&elfbuf[elfbufoffset], 1328 " %s", empty_name); 1329 } 1330 } else { 1331 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s", 1332 empty_name); 1333 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s", 1334 empty_name); 1335 } 1336 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%lx", lhp->rh_uid); 1337 if (((pwp = getpwuid(lhp->rh_uid)) != NULL) && (pwp->pw_name != NULL)) { 1338 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " \"%s\"", 1339 pwp->pw_name); 1340 } else { 1341 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " %s", 1342 empty_name); 1343 } 1344 elfbufoffset += sprintf(&elfbuf[elfbufoffset], " 0x%lx", lhp->rh_gid); 1345 elfrec->bufoffset = elfbufoffset; 1346 } 1347 1348 static void 1349 nfsl_elf_buffer_header_print(struct nfsl_log_file *elfrec, 1350 nfslog_buffer_header *bufhdr) 1351 { 1352 int rc; 1353 struct utsname name; 1354 char *elfbuf = elfrec->buf; 1355 int elfbufoffset = elfrec->bufoffset; 1356 1357 rc = uname(&name); 1358 elfbufoffset += sprintf(&elfbuf[elfbufoffset], 1359 "#Version %d.0\n#Software \"%s\"\n", 1360 bufhdr->bh_version, ((rc >= 0) ? name.sysname : empty_name)); 1361 elfbufoffset += sprintf(&elfbuf[elfbufoffset], "#Date %s\n", 1362 nfsl_get_date((time_t)bufhdr->bh_timestamp.tv_sec)); 1363 elfbufoffset += sprintf(&elfbuf[elfbufoffset], "#Remark %s\n", 1364 empty_name); 1365 elfbufoffset += sprintf(&elfbuf[elfbufoffset], 1366 "#Fields: time bytes tag"); 1367 elfbufoffset += sprintf(&elfbuf[elfbufoffset], 1368 " rpc-program rpc-version rpc-procedure"); 1369 elfbufoffset += sprintf(&elfbuf[elfbufoffset], 1370 " auth-flavor s-user-name s-uid uid u-name gid net-id c-ip"); 1371 elfbufoffset += sprintf(&elfbuf[elfbufoffset], 1372 " c-dns s-dns status rpcarg-path"); 1373 elfbufoffset += sprintf(&elfbuf[elfbufoffset], 1374 " rpc-arguments... rpc-response...\n"); 1375 elfrec->bufoffset = elfbufoffset; 1376 } 1377 1378 /* 1379 * nfsl_find_elf_dispatch - get the dispatch struct for this request 1380 */ 1381 static struct nfsl_proc_disp * 1382 nfsl_find_elf_dispatch(nfslog_request_record *logrec, char **prognamep) 1383 { 1384 nfslog_record_header *logrechdr = &logrec->re_header; 1385 struct nfsl_prog_disp *progtable; /* prog struct */ 1386 struct nfsl_vers_disp *verstable; /* version struct */ 1387 int i, vers; 1388 1389 /* Find prog element - search because can't use prog as array index */ 1390 for (i = 0; (i < nfsl_elf_dispatch_table_arglen) && 1391 (logrechdr->rh_prognum != nfsl_elf_dispatch_table[i].nfsl_dis_prog); 1392 i++); 1393 if (i >= nfsl_elf_dispatch_table_arglen) { /* program not logged */ 1394 /* not an error */ 1395 return (NULL); 1396 } 1397 progtable = &nfsl_elf_dispatch_table[i]; 1398 /* Find vers element - no validity check - if here it's valid vers */ 1399 vers = logrechdr->rh_version - progtable->nfsl_dis_versmin; 1400 verstable = &progtable->nfsl_dis_vers_table[vers]; 1401 /* Find proc element - no validity check - if here it's valid proc */ 1402 *prognamep = progtable->progname; 1403 return (&verstable->nfsl_dis_proc_table[logrechdr->rh_procnum]); 1404 } 1405 1406 /* 1407 * nfsl_elf_rpc_print - Print the record buffer. 1408 */ 1409 static void 1410 nfsl_elf_rpc_print(struct nfsl_log_file *elfrec, 1411 nfslog_request_record *logrec, struct nfsl_proc_disp *disp, 1412 char *progname, char *path1, char *path2) 1413 { 1414 if (debug > 1) { 1415 (void) printf("%s %d %s", progname, 1416 logrec->re_header.rh_version, disp->procname); 1417 (void) printf(": '%s', '%s'\n", 1418 ((path1 != NULL) ? path1 : empty_name), 1419 ((path2 != NULL) ? path2 : empty_name)); 1420 } 1421 /* 1422 * XXXX programs using this file to get a usable record should 1423 * take "record" struct. 1424 */ 1425 /* 1426 * Print the variable fields: 1427 * principal name 1428 * netid 1429 * ip address 1430 * rpc args 1431 * rpc res 1432 * Use the displacements calculated earlier... 1433 */ 1434 1435 /* 1436 * Fields: time bytes tag rpc-program rpc-version rpc-procedure 1437 * auth-flavor s-user-name s-uid uid u-name gid net-id c-ip 1438 * c-dns s-dns status rpcarg-path <arguments> <response> 1439 */ 1440 nfsl_elf_record_header_print(elfrec, &logrec->re_header, 1441 logrec->re_principal_name, logrec->re_tag, 1442 disp, progname); 1443 if ((logrec->re_netid != NULL) && (logrec->re_netid[0] != '\0')) { 1444 elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], 1445 " \"%s\"", logrec->re_netid); 1446 } else { 1447 elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], 1448 " %s", empty_name); 1449 } 1450 nfsl_ipaddr_print(elfrec, &logrec->re_ipaddr); 1451 elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], 1452 " \"%s\"", hostname); 1453 /* Next is return status */ 1454 (*disp->nfsl_dis_res)(elfrec, logrec->re_rpc_res, TRUE); 1455 /* Next is argpath */ 1456 if (path1 != NULL) { 1457 elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], 1458 " \"%s\"", path1); 1459 } else { 1460 elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], 1461 " %s", empty_name); 1462 } 1463 /* 1464 * path2 is non-empty for rename/link type operations. If it is non- 1465 * empty print it here as it's a part of the args 1466 */ 1467 if (path2 != NULL) { 1468 elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], 1469 " \"%s\"", path2); 1470 } 1471 /* Next print formatted rpc args */ 1472 (*disp->nfsl_dis_args)(elfrec, logrec->re_rpc_arg); 1473 /* Next print formatted rpc res (minus status) */ 1474 (*disp->nfsl_dis_res)(elfrec, logrec->re_rpc_res, FALSE); 1475 elfrec->bufoffset += sprintf(&elfrec->buf[elfrec->bufoffset], "\n"); 1476 } 1477 1478 /* 1479 * nfsl_log_file_add - add a new record to the list 1480 */ 1481 static void 1482 nfsl_log_file_add(struct nfsl_log_file *elfrec, 1483 struct nfsl_log_file **elf_listp) 1484 { 1485 elfrec->next = *elf_listp; 1486 elfrec->prev = NULL; 1487 if (*elf_listp != NULL) { 1488 (*elf_listp)->prev = elfrec; 1489 } 1490 *elf_listp = elfrec; 1491 } 1492 1493 /* 1494 * nfsl_log_file_find - finds a record in the list, given a cookie (== elfrec) 1495 * Returns the record. 1496 */ 1497 static struct nfsl_log_file * 1498 nfsl_log_file_find(struct nfsl_log_file *elfrec, 1499 struct nfsl_log_file *elf_list) 1500 { 1501 struct nfsl_log_file *rec; 1502 1503 for (rec = elf_list; (rec != NULL) && (rec != elfrec); 1504 rec = rec->next); 1505 return (rec); 1506 } 1507 1508 /* 1509 * nfsl_log_file_del - delete a record from the list, does not free rec. 1510 * Returns the deleted record. 1511 */ 1512 static struct nfsl_log_file * 1513 nfsl_log_file_del(struct nfsl_log_file *elfrec, 1514 struct nfsl_log_file **elf_listp) 1515 { 1516 struct nfsl_log_file *rec; 1517 1518 if ((rec = nfsl_log_file_find(elfrec, *elf_listp)) == NULL) { 1519 return (NULL); 1520 } 1521 if (rec->prev != NULL) { 1522 rec->prev->next = rec->next; 1523 } else { 1524 *elf_listp = rec->next; 1525 } 1526 if (rec->next != NULL) { 1527 rec->next->prev = rec->prev; 1528 } 1529 return (rec); 1530 } 1531 1532 /* 1533 * nfsl_log_file_free - frees a record 1534 */ 1535 static void 1536 nfsl_log_file_free(struct nfsl_log_file *elfrec) 1537 { 1538 if (elfrec == NULL) 1539 return; 1540 if (elfrec->path != NULL) 1541 free(elfrec->path); 1542 if (elfrec->buf != NULL) 1543 free(elfrec->buf); 1544 free(elfrec); 1545 } 1546 1547 /* 1548 * Exported Functions 1549 */ 1550 1551 /* 1552 * nfslog_open_elf_file - open the output elf file and mallocs needed buffers 1553 * Returns a pointer to the nfsl_log_file on success, NULL on error. 1554 * 1555 * *error contains the last error encountered on this object, It can 1556 * be used to avoid reporting the same error endlessly, by comparing 1557 * the current error to the last error. It is reset to the current error 1558 * code on return. 1559 */ 1560 void * 1561 nfslog_open_elf_file(char *elfpath, nfslog_buffer_header *bufhdr, int *error) 1562 { 1563 struct nfsl_log_file *elfrec; 1564 struct stat stat_buf; 1565 int preverror = *error; 1566 1567 if ((elfrec = malloc(sizeof (*elfrec))) == NULL) { 1568 *error = errno; 1569 if (*error != preverror) { 1570 syslog(LOG_ERR, gettext("nfslog_open_elf_file: %s"), 1571 strerror(*error)); 1572 } 1573 return (NULL); 1574 } 1575 bzero(elfrec, sizeof (*elfrec)); 1576 1577 elfrec->buf = (char *)malloc(DFLT_BUFFERSIZE + DFLT_OVFSIZE); 1578 if (elfrec->buf == NULL) { 1579 *error = errno; 1580 if (*error != preverror) { 1581 syslog(LOG_ERR, gettext("nfslog_open_elf_file: %s"), 1582 strerror(*error)); 1583 } 1584 nfsl_log_file_free(elfrec); 1585 return (NULL); 1586 } 1587 1588 if ((elfrec->path = strdup(elfpath)) == NULL) { 1589 *error = errno; 1590 if (*error != preverror) { 1591 syslog(LOG_ERR, gettext("nfslog_open_elf_file: %s"), 1592 strerror(*error)); 1593 } 1594 nfsl_log_file_free(elfrec); 1595 return (NULL); 1596 } 1597 1598 if ((elfrec->fp = fopen(elfpath, "a")) == NULL) { 1599 *error = errno; 1600 if (*error != preverror) { 1601 syslog(LOG_ERR, gettext("Cannot open '%s': %s"), 1602 elfpath, strerror(*error)); 1603 } 1604 nfsl_log_file_free(elfrec); 1605 return (NULL); 1606 } 1607 1608 if (stat(elfpath, &stat_buf) == -1) { 1609 *error = errno; 1610 if (*error != preverror) { 1611 syslog(LOG_ERR, gettext("Cannot stat '%s': %s"), 1612 elfpath, strerror(*error)); 1613 } 1614 (void) fclose(elfrec->fp); 1615 nfsl_log_file_free(elfrec); 1616 return (NULL); 1617 } 1618 1619 nfsl_log_file_add(elfrec, &elf_file_list); 1620 1621 if (stat_buf.st_size == 0) { 1622 /* 1623 * Print header unto logfile 1624 */ 1625 nfsl_elf_buffer_header_print(elfrec, bufhdr); 1626 } 1627 1628 if (hostname[0] == '\0') { 1629 (void) gethostname(hostname, MAXHOSTNAMELEN); 1630 } 1631 1632 return (elfrec); 1633 } 1634 1635 /* 1636 * nfslog_close_elf_file - close elffile and write out last buffer 1637 */ 1638 void 1639 nfslog_close_elf_file(void **elfcookie) 1640 { 1641 struct nfsl_log_file *elfrec; 1642 1643 if ((*elfcookie == NULL) || ((elfrec = nfsl_log_file_del( 1644 *elfcookie, &elf_file_list)) == NULL)) { 1645 *elfcookie = NULL; 1646 return; 1647 } 1648 if (elfrec->fp != NULL) { 1649 /* Write the last output buffer to disk */ 1650 (void) nfsl_write_elfbuf(elfrec); 1651 (void) fclose(elfrec->fp); 1652 } 1653 nfsl_log_file_free(elfrec); 1654 *elfcookie = NULL; 1655 } 1656 1657 /* 1658 * nfslog_process_elf_rec - processes the record in the buffer and outputs 1659 * to the elf log. 1660 * Return 0 for success, errno else. 1661 */ 1662 int 1663 nfslog_process_elf_rec(void *elfcookie, nfslog_request_record *logrec, 1664 char *path1, char *path2) 1665 { 1666 struct nfsl_log_file *elfrec; 1667 struct nfsl_proc_disp *disp; 1668 char *progname; 1669 1670 if ((elfrec = nfsl_log_file_find(elfcookie, elf_file_list)) == NULL) { 1671 return (EINVAL); 1672 } 1673 /* Make sure there is room */ 1674 if (elfrec->bufoffset > DFLT_BUFFERSIZE) { 1675 if (nfsl_write_elfbuf(elfrec) < 0) { 1676 return (errno); 1677 } 1678 } 1679 if ((disp = nfsl_find_elf_dispatch(logrec, &progname)) != NULL) { 1680 nfsl_elf_rpc_print(elfrec, logrec, disp, progname, 1681 path1, path2); 1682 } 1683 return (0); 1684 } 1685