Imported Upstream version 2.4.3
[platform/upstream/audit.git] / auparse / interpret.c
1 /*
2 * interpret.c - Lookup values to something more readable
3 * Copyright (c) 2007-09,2011-14 Red Hat Inc., Durham, North Carolina.
4 * All Rights Reserved. 
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 *
20 * Authors:
21 *   Steve Grubb <sgrubb@redhat.com>
22 */
23
24 #include "config.h"
25 #include "nvlist.h"
26 #include "nvpair.h"
27 #include "libaudit.h"
28 #include "internal.h"
29 #include "interpret.h"
30 #include "auparse-idata.h"
31 #include <stddef.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <fcntl.h>
35 #include <ctype.h>
36 #include <errno.h>
37 #include <string.h>
38 #include <pwd.h>
39 #include <grp.h>
40 #include <sys/stat.h>
41 #include <linux/net.h>
42 #include <netdb.h>
43 #include <sys/un.h>
44 #include <linux/ax25.h>
45 #include <linux/atm.h>
46 #include <linux/x25.h>
47 #include <linux/if.h>   // FIXME: remove when ipx.h is fixed
48 #include <linux/ipx.h>
49 #include <linux/capability.h>
50 #include <sys/personality.h>
51 #include <sys/prctl.h>
52 #include <sched.h>
53 #include "auparse-defs.h"
54 #include "gen_tables.h"
55
56 #if !HAVE_DECL_ADDR_NO_RANDOMIZE
57 # define ADDR_NO_RANDOMIZE       0x0040000
58 #endif
59
60 /* This is from asm/ipc.h. Copying it for now as some platforms
61  * have broken headers. */
62 #define SEMOP            1
63 #define SEMGET           2
64 #define SEMCTL           3
65 #define SEMTIMEDOP       4
66 #define MSGSND          11
67 #define MSGRCV          12
68 #define MSGGET          13
69 #define MSGCTL          14
70 #define SHMAT           21
71 #define SHMDT           22
72 #define SHMGET          23
73 #define SHMCTL          24
74 #define DIPC            25
75
76 #include "captabs.h"
77 #include "clone-flagtabs.h"
78 #include "epoll_ctls.h"
79 #include "famtabs.h"
80 #include "fcntl-cmdtabs.h"
81 #include "flagtabs.h"
82 #include "ipctabs.h"
83 #include "ipccmdtabs.h"
84 #include "mmaptabs.h"
85 #include "mounttabs.h"
86 #include "open-flagtabs.h"
87 #include "persontabs.h"
88 #include "prottabs.h"
89 #include "ptracetabs.h"
90 #include "recvtabs.h"
91 #include "rlimittabs.h"
92 #include "seektabs.h"
93 #include "socktabs.h"
94 #include "socktypetabs.h"
95 #include "signaltabs.h"
96 #include "clocktabs.h"
97 #include "typetabs.h"
98 #include "nfprototabs.h"
99 #include "icmptypetabs.h"
100 #include "seccomptabs.h"
101 #include "accesstabs.h"
102 #include "prctl_opttabs.h"
103 #include "schedtabs.h"
104 #include "shm_modetabs.h"
105 #include "sockoptnametabs.h"
106 #include "sockleveltabs.h"
107 #include "ipoptnametabs.h"
108 #include "ip6optnametabs.h"
109 #include "tcpoptnametabs.h"
110 #include "pktoptnametabs.h"
111 #include "umounttabs.h"
112 #include "ioctlreqtabs.h"
113
114 typedef enum { AVC_UNSET, AVC_DENIED, AVC_GRANTED } avc_t;
115 typedef enum { S_UNSET=-1, S_FAILED, S_SUCCESS } success_t;
116
117 static const char *print_signals(const char *val, unsigned int base);
118
119
120 /*
121  * This function will take a pointer to a 2 byte Ascii character buffer and
122  * return the actual hex value.
123  */
124 static unsigned char x2c(const unsigned char *buf)
125 {
126         static const char AsciiArray[17] = "0123456789ABCDEF";
127         char *ptr;
128         unsigned char total=0;
129
130         ptr = strchr(AsciiArray, (char)toupper(buf[0]));
131         if (ptr)
132                 total = (unsigned char)(((ptr-AsciiArray) & 0x0F)<<4);
133         ptr = strchr(AsciiArray, (char)toupper(buf[1]));
134         if (ptr)
135                 total += (unsigned char)((ptr-AsciiArray) & 0x0F);
136
137         return total;
138 }
139
140 static int is_hex_string(const char *str)
141 {
142         while (*str) {
143                 if (!isxdigit(*str))
144                         return 0;
145                 str++;
146         }
147         return 1;
148 }
149
150 /* returns a freshly malloc'ed and converted buffer */
151 char *au_unescape(char *buf)
152 {
153         int len, i;
154         char saved, *str, *ptr = buf;
155
156         /* Find the end of the name */
157         if (*ptr == '(') {
158                 ptr = strchr(ptr, ')');
159                 if (ptr == NULL)
160                         return NULL;
161                 else
162                         ptr++;
163         } else {
164                 while (isxdigit(*ptr))
165                         ptr++;
166         }
167         saved = *ptr;
168         *ptr = 0;
169         str = strdup(buf);
170         *ptr = saved;
171
172         /* See if its '(null)' from the kernel */
173         if (*buf == '(')
174                 return str;
175
176         /* We can get away with this since the buffer is 2 times
177          * bigger than what we are putting there.
178          */
179         len = strlen(str);
180         if (len < 2) {
181                 free(str);
182                 return NULL;
183         }
184         ptr = str;
185         for (i=0; i<len; i+=2) {
186                 *ptr = x2c((unsigned char *)&str[i]);
187                 ptr++;
188         }
189         *ptr = 0;
190         return str;
191 }
192
193 static const char *success[3]= { "unset", "no", "yes" };
194 static const char *aulookup_success(int s)
195 {
196         switch (s)
197         {
198                 default:
199                         return success[0];
200                         break;
201                 case S_FAILED:
202                         return success[1];
203                         break;
204                 case S_SUCCESS:
205                         return success[2];
206                         break;
207         }
208 }
209
210 static nvpair uid_nvl;
211 static int uid_list_created=0;
212 static const char *aulookup_uid(uid_t uid, char *buf, size_t size)
213 {
214         char *name = NULL;
215         int rc;
216
217         if (uid == -1) {
218                 snprintf(buf, size, "unset");
219                 return buf;
220         }
221
222         // Check the cache first
223         if (uid_list_created == 0) {
224                 nvpair_create(&uid_nvl);
225                 nvpair_clear(&uid_nvl);
226                 uid_list_created = 1;
227         }
228         rc = nvpair_find_val(&uid_nvl, uid);
229         if (rc) {
230                 name = uid_nvl.cur->name;
231         } else {
232                 // Add it to cache
233                 struct passwd *pw;
234                 pw = getpwuid(uid);
235                 if (pw) {
236                         nvpnode nv;
237                         nv.name = strdup(pw->pw_name);
238                         nv.val = uid;
239                         nvpair_append(&uid_nvl, &nv);
240                         name = uid_nvl.cur->name;
241                 }
242         }
243         if (name != NULL)
244                 snprintf(buf, size, "%s", name);
245         else
246                 snprintf(buf, size, "unknown(%d)", uid);
247         return buf;
248 }
249
250 void aulookup_destroy_uid_list(void)
251 {
252         if (uid_list_created == 0)
253                 return;
254
255         nvpair_clear(&uid_nvl); 
256         uid_list_created = 0;
257 }
258
259 static nvpair gid_nvl;
260 static int gid_list_created=0;
261 static const char *aulookup_gid(gid_t gid, char *buf, size_t size)
262 {
263         char *name = NULL;
264         int rc;
265
266         if (gid == -1) {
267                 snprintf(buf, size, "unset");
268                 return buf;
269         }
270
271         // Check the cache first
272         if (gid_list_created == 0) {
273                 nvpair_create(&gid_nvl);
274                 nvpair_clear(&gid_nvl);
275                 gid_list_created = 1;
276         }
277         rc = nvpair_find_val(&gid_nvl, gid);
278         if (rc) {
279                 name = gid_nvl.cur->name;
280         } else {
281                 // Add it to cache
282                 struct group *gr;
283                 gr = getgrgid(gid);
284                 if (gr) {
285                         nvpnode nv;
286                         nv.name = strdup(gr->gr_name);
287                         nv.val = gid;
288                         nvpair_append(&gid_nvl, &nv);
289                         name = gid_nvl.cur->name;
290                 }
291         }
292         if (name != NULL)
293                 snprintf(buf, size, "%s", name);
294         else
295                 snprintf(buf, size, "unknown(%d)", gid);
296         return buf;
297 }
298
299 void aulookup_destroy_gid_list(void)
300 {
301         if (gid_list_created == 0)
302                 return;
303
304         nvpair_clear(&gid_nvl); 
305         gid_list_created = 0;
306 }
307
308 static const char *print_uid(const char *val, unsigned int base)
309 {
310         int uid;
311         char name[64];
312
313         errno = 0;
314         uid = strtoul(val, NULL, base);
315         if (errno) {
316                 char *out;
317                 if (asprintf(&out, "conversion error(%s)", val) < 0)
318                         out = NULL;
319                 return out;
320         }
321
322         return strdup(aulookup_uid(uid, name, sizeof(name)));
323 }
324
325 static const char *print_gid(const char *val, unsigned int base)
326 {
327         int gid;
328         char name[64];
329
330         errno = 0;
331         gid = strtoul(val, NULL, base);
332         if (errno) {
333                 char *out;
334                 if (asprintf(&out, "conversion error(%s)", val) < 0)
335                         out = NULL;
336                 return out;
337         }
338
339         return strdup(aulookup_gid(gid, name, sizeof(name)));
340 }
341
342 static const char *print_arch(const char *val, unsigned int machine)
343 {
344         const char *ptr;
345         char *out;
346
347         if (machine > MACH_AARCH64) {
348                 unsigned int ival;
349
350                 errno = 0;
351                 ival = strtoul(val, NULL, 16);
352                 if (errno) {
353                         if (asprintf(&out, "conversion error(%s) ", val) < 0)
354                                 out = NULL;
355                         return out;
356                 }
357                 machine = audit_elf_to_machine(ival);
358         }
359         if ((int)machine < 0) {
360                 if (asprintf(&out, "unknown elf type(%s)", val) < 0)
361                         out = NULL;
362                 return out;
363         }
364         ptr = audit_machine_to_name(machine);
365         if (ptr)
366                 return strdup(ptr);
367         else {
368                 if (asprintf(&out, "unknown machine type(%d)", machine) < 0)
369                         out = NULL;
370                 return out;
371         }
372 }
373
374 static const char *print_ipccall(const char *val, unsigned int base)
375 {
376         int a0;
377         char *out;
378         const char *func = NULL;
379
380         errno = 0;
381         a0 = strtol(val, NULL, base);
382         if (errno) {
383                 char *out;
384                 if (asprintf(&out, "conversion error(%s)", val) < 0)
385                         out = NULL;
386                 return out;
387         }
388         func = ipc_i2s(a0);
389         if (func)
390                 return strdup(func);
391         else {
392                 if (asprintf(&out, "unknown ipccall(%s)", val) < 0)
393                         out = NULL;
394                 return out;
395         }
396 }
397
398 static const char *print_socketcall(const char *val, unsigned int base)
399 {
400         int a0;
401         char *out;
402         const char *func = NULL;
403
404         errno = 0;
405         a0 = strtol(val, NULL, base);
406         if (errno) {
407                 char *out;
408                 if (asprintf(&out, "conversion error(%s)", val) < 0)
409                         out = NULL;
410                 return out;
411         }
412         func = sock_i2s(a0);
413         if (func)
414                 return strdup(func);
415         else {
416                 if (asprintf(&out, "unknown socketcall(%s)", val) < 0)
417                         out = NULL;
418                 return out;
419         }
420 }
421
422 static const char *print_syscall(const idata *id)
423 {
424         const char *sys;
425         char *out;
426         int machine = id->machine, syscall = id->syscall;
427         unsigned long long a0 = id->a0;
428
429         if (machine < 0)
430                 machine = audit_detect_machine();
431         if (machine < 0) {
432                 out = strdup(id->val);
433                 return out;
434         }
435         sys = audit_syscall_to_name(syscall, machine);
436         if (sys) {
437                 const char *func = NULL;
438                 if (strcmp(sys, "socketcall") == 0) {
439                         if ((int)a0 == a0)
440                                 func = sock_i2s(a0);
441                 } else if (strcmp(sys, "ipc") == 0)
442                         if ((int)a0 == a0)
443                                 func = ipc_i2s(a0);
444                 if (func) {
445                         if (asprintf(&out, "%s(%s)", sys, func) < 0)
446                                 out = NULL;
447                 } else
448                         return strdup(sys);
449         } else {
450                 if (asprintf(&out, "unknown syscall(%d)", syscall) < 0)
451                         out = NULL;
452         }
453
454         return out;
455 }
456
457 static const char *print_exit(const char *val)
458 {
459         long long ival;
460         char *out;
461
462         errno = 0;
463         ival = strtoll(val, NULL, 10);
464         if (errno) {
465                 if (asprintf(&out, "conversion error(%s)", val) < 0)
466                         out = NULL;
467                 return out;
468         }
469
470         if (ival < 0) {
471                 if (asprintf(&out, "%lld(%s)", ival, strerror(-ival)) < 0)
472                         out = NULL;
473                 return out;
474         }
475         return strdup(val);
476 }
477
478 static const char *print_escaped(const char *val)
479 {
480         const char *out;
481
482         if (*val == '"') {
483                 char *term;
484                 val++;
485                 term = strchr(val, '"');
486                 if (term == NULL)
487                         return strdup(" ");
488                 *term = 0;
489                 out = strdup(val);
490                 *term = '"';
491                 return out;
492 // FIXME: working here...was trying to detect (null) and handle that
493 // differently. The other 2 should have " around the file names.
494 /*      } else if (*val == '(') {
495                 char *term;
496                 val++;
497                 term = strchr(val, ' ');
498                 if (term == NULL)
499                         return;
500                 *term = 0;
501                 printf("%s ", val); */
502         } else if (val[0] == '0' && val[1] == '0')
503                 out = au_unescape((char *)&val[2]); // Abstract name af_unix
504         else
505                 out = au_unescape((char *)val);
506         if (out)
507                 return out;
508         return strdup(val); // Something is wrong with string, just send as is
509 }
510
511 static const char *print_proctitle(const char *val)
512 {
513         char *out = (char *)print_escaped(val);
514         if (*val != '"') {
515                 size_t len = strlen(val) / 2;
516                 const char *end = out + len;
517                 char *ptr = out;
518                 while ((ptr  = rawmemchr(ptr, '\0'))) {
519                         if (ptr >= end)
520                                 break;
521                         *ptr = ' ';
522                         ptr++;
523                 }
524         }
525         return out;
526 }
527
528 static const char *print_perm(const char *val)
529 {
530         int ival, printed=0;
531         char buf[32];
532
533         errno = 0;
534         ival = strtol(val, NULL, 10);
535         if (errno) {
536                 char *out;
537                 if (asprintf(&out, "conversion error(%s)", val) < 0)
538                         out = NULL;
539                 return out;
540         }
541
542         buf[0] = 0;
543
544         /* The kernel treats nothing (0x00) as everything (0x0F) */
545         if (ival == 0)
546                 ival = 0x0F;
547         if (ival & AUDIT_PERM_READ) {
548                 strcat(buf, "read");
549                 printed = 1;
550         }
551         if (ival & AUDIT_PERM_WRITE) {
552                 if (printed)
553                         strcat(buf, ",write");
554                 else
555                         strcat(buf, "write");
556                 printed = 1;
557         }
558         if (ival & AUDIT_PERM_EXEC) {
559                 if (printed)
560                         strcat(buf, ",exec");
561                 else
562                         strcat(buf, "exec");
563                 printed = 1;
564         }
565         if (ival & AUDIT_PERM_ATTR) {
566                 if (printed)
567                         strcat(buf, ",attr");
568                 else
569                         strcat(buf, "attr");
570         }
571         return strdup(buf);
572 }
573
574 static const char *print_mode(const char *val, unsigned int base)
575 {
576         unsigned int ival;
577         char *out, buf[48];
578         const char *name;
579
580         errno = 0;
581         ival = strtoul(val, NULL, base);
582         if (errno) {
583                 if (asprintf(&out, "conversion error(%s)", val) < 0)
584                         out = NULL;
585                 return out;
586         }
587
588         // detect the file type
589         name = audit_ftype_to_name(ival & S_IFMT);
590         if (name != NULL)
591                 strcpy(buf, name);
592         else {
593                 unsigned first_ifmt_bit;
594
595                 // The lowest-valued "1" bit in S_IFMT
596                 first_ifmt_bit = S_IFMT & ~(S_IFMT - 1);
597                 sprintf(buf, "%03o", (ival & S_IFMT) / first_ifmt_bit);
598         }
599
600         // check on special bits
601         if (S_ISUID & ival)
602                 strcat(buf, ",suid");
603         if (S_ISGID & ival)
604                 strcat(buf, ",sgid");
605         if (S_ISVTX & ival)
606                 strcat(buf, ",sticky");
607
608         // and the read, write, execute flags in octal
609         if (asprintf(&out, "%s,%03o", buf,
610                      (S_IRWXU|S_IRWXG|S_IRWXO) & ival) < 0)
611                 out = NULL;
612         return out;
613 }
614
615 static const char *print_mode_short_int(unsigned int ival)
616 {
617         char *out, buf[48];
618
619         // check on special bits
620         buf[0] = 0;
621         if (S_ISUID & ival)
622                 strcat(buf, "suid");
623         if (S_ISGID & ival) {
624                 if (buf[0])
625                         strcat(buf, ",");
626                 strcat(buf, "sgid");
627         }
628         if (S_ISVTX & ival) {
629                 if (buf[0])
630                         strcat(buf, ",");
631                 strcat(buf, "sticky");
632         }
633
634         // and the read, write, execute flags in octal
635         if (buf[0] == 0) {
636                 if (asprintf(&out, "0%03o",
637                              (S_IRWXU|S_IRWXG|S_IRWXO) & ival) < 0)
638                         out = NULL;
639         } else
640                 if (asprintf(&out, "%s,0%03o", buf,
641                              (S_IRWXU|S_IRWXG|S_IRWXO) & ival) < 0)
642                         out = NULL;
643         return out;
644 }
645
646 static const char *print_mode_short(const char *val, int base)
647 {
648         unsigned int ival;
649         char *out;
650
651         errno = 0;
652         ival = strtoul(val, NULL, base);
653         if (errno) {
654                 if (asprintf(&out, "conversion error(%s)", val) < 0)
655                         out = NULL;
656                 return out;
657         }
658         return print_mode_short_int(ival);
659 }
660
661 static const char *print_socket_domain(const char *val)
662 {
663         int i;
664         char *out;
665         const char *str;
666
667         errno = 0;
668         i = strtoul(val, NULL, 16);
669         if (errno) {
670                 if (asprintf(&out, "conversion error(%s)", val) < 0)
671                         out = NULL;
672                 return out;
673         }
674         str = fam_i2s(i);
675         if (str == NULL) {
676                 if (asprintf(&out, "unknown family(0x%s)", val) < 0)
677                         out = NULL;
678                 return out;
679         } else
680                 return strdup(str);
681 }
682
683 static const char *print_socket_type(const char *val)
684 {
685         unsigned int type;
686         char *out;
687         const char *str;
688
689         errno = 0;
690         type = 0xFF & strtoul(val, NULL, 16);
691         if (errno) {
692                 if (asprintf(&out, "conversion error(%s)", val) < 0)
693                         out = NULL;
694                 return out;
695         }
696         str = sock_type_i2s(type);
697         if (str == NULL) {
698                 if (asprintf(&out, "unknown type(%s)", val) < 0)
699                         out = NULL;
700                 return out;
701         } else
702                 return strdup(str);
703 }
704
705 static const char *print_socket_proto(const char *val)
706 {
707         unsigned int proto;
708         char *out;
709         struct protoent *p;
710
711         errno = 0;
712         proto = strtoul(val, NULL, 16);
713         if (errno) {
714                 if (asprintf(&out, "conversion error(%s)", val) < 0)
715                         out = NULL;
716                 return out;
717         }
718         p = getprotobynumber(proto);
719         if (p == NULL) {
720                 if (asprintf(&out, "unknown proto(%s)", val) < 0)
721                         out = NULL;
722                 return out;
723         } else
724                 return strdup(p->p_name);
725 }
726
727 static const char *print_sockaddr(const char *val)
728 {
729         int slen, rc = 0;
730         const struct sockaddr *saddr;
731         char name[NI_MAXHOST], serv[NI_MAXSERV];
732         const char *host;
733         char *out = NULL;
734         const char *str;
735
736         slen = strlen(val)/2;
737         host = au_unescape((char *)val);
738         if (host == NULL) {
739                 if (asprintf(&out, "malformed host(%s)", val) < 0)
740                         out = NULL;
741                 return out;
742         }
743         saddr = (struct sockaddr *)host;
744
745
746         str = fam_i2s(saddr->sa_family);
747         if (str == NULL) {
748                 if (asprintf(&out, "unknown family(%d)", saddr->sa_family) < 0)
749                         out = NULL;
750                 free((char *)host);
751                 return out;
752         }
753
754         // Now print address for some families
755         switch (saddr->sa_family) {
756                 case AF_LOCAL:
757                         {
758                                 const struct sockaddr_un *un =
759                                         (struct sockaddr_un *)saddr;
760                                 if (un->sun_path[0])
761                                         rc = asprintf(&out, "%s %s", str,
762                                                       un->sun_path);
763                                 else // abstract name
764                                         rc = asprintf(&out, "%s %.108s", str,
765                                                       &un->sun_path[1]);
766                         }
767                         break;
768                 case AF_INET:
769                         if (slen < sizeof(struct sockaddr_in)) {
770                                 rc = asprintf(&out, "%s sockaddr len too short",
771                                               str);
772                                 break;
773                         }
774                         slen = sizeof(struct sockaddr_in);
775                         if (getnameinfo(saddr, slen, name, NI_MAXHOST, serv,
776                                 NI_MAXSERV, NI_NUMERICHOST |
777                                         NI_NUMERICSERV) == 0 ) {
778                                 rc = asprintf(&out, "%s host:%s serv:%s", str,
779                                               name, serv);
780                         } else
781                                 rc = asprintf(&out, "%s (error resolving addr)",
782                                               str);
783                         break;
784                 case AF_AX25:
785                         {
786                                 const struct sockaddr_ax25 *x =
787                                                 (struct sockaddr_ax25 *)saddr;
788                                 rc = asprintf(&out, "%s call:%c%c%c%c%c%c%c",
789                                               str,
790                                               x->sax25_call.ax25_call[0],
791                                               x->sax25_call.ax25_call[1],
792                                               x->sax25_call.ax25_call[2],
793                                               x->sax25_call.ax25_call[3],
794                                               x->sax25_call.ax25_call[4],
795                                               x->sax25_call.ax25_call[5],
796                                               x->sax25_call.ax25_call[6]);
797                         }
798                         break;
799                 case AF_IPX:
800                         {
801                                 const struct sockaddr_ipx *ip =
802                                                 (struct sockaddr_ipx *)saddr;
803                                 rc = asprintf(&out, "%s port:%d net:%u", str,
804                                               ip->sipx_port, ip->sipx_network);
805                         }
806                         break;
807                 case AF_ATMPVC:
808                         {
809                                 const struct sockaddr_atmpvc* at =
810                                         (struct sockaddr_atmpvc *)saddr;
811                                 rc = asprintf(&out, "%s int:%d", str,
812                                               at->sap_addr.itf);
813                         }
814                         break;
815                 case AF_X25:
816                         {
817                                 const struct sockaddr_x25* x =
818                                         (struct sockaddr_x25 *)saddr;
819                                 rc = asprintf(&out, "%s addr:%.15s", str,
820                                               x->sx25_addr.x25_addr);
821                         }
822                         break;
823                 case AF_INET6:
824                         if (slen < sizeof(struct sockaddr_in6)) {
825                                 rc = asprintf(&out,
826                                               "%s sockaddr6 len too short",
827                                               str);
828                                 break;
829                         }
830                         slen = sizeof(struct sockaddr_in6);
831                         if (getnameinfo(saddr, slen, name, NI_MAXHOST, serv,
832                                 NI_MAXSERV, NI_NUMERICHOST |
833                                         NI_NUMERICSERV) == 0 ) {
834                                 rc = asprintf(&out, "%s host:%s serv:%s", str,
835                                               name, serv);
836                         } else
837                                 rc = asprintf(&out, "%s (error resolving addr)",
838                                               str);
839                         break;
840                 case AF_NETLINK:
841                         {
842                                 const struct sockaddr_nl *n =
843                                                 (struct sockaddr_nl *)saddr;
844                                 rc = asprintf(&out, "%s pid:%u", str,
845                                               n->nl_pid);
846                         }
847                         break;
848         }
849         if (rc < 0)
850                 out = NULL;
851         free((char *)host);
852         return out;
853 }
854
855 /* This is only used in the RHEL4 kernel */
856 static const char *print_flags(const char *val)
857 {
858         int flags, cnt = 0;
859         size_t i;
860         char *out, buf[80];
861
862         errno = 0;
863         flags = strtoul(val, NULL, 16);
864         if (errno) {
865                 if (asprintf(&out, "conversion error(%s)", val) < 0)
866                         out = NULL;
867                 return out;
868         }
869         if (flags == 0) {
870                 if (asprintf(&out, "none") < 0)
871                         out = NULL;
872                 return out;
873         }
874         buf[0] = 0;
875         for (i=0; i<FLAG_NUM_ENTRIES; i++) {
876                 if (flag_table[i].value & flags) {
877                         if (!cnt) {
878                                 strcat(buf,
879                                        flag_strings + flag_table[i].offset);
880                                 cnt++;
881                         } else {
882                                 strcat(buf, ",");
883                                 strcat(buf,
884                                        flag_strings + flag_table[i].offset);
885                         }
886                 }
887         }
888         if (buf[0] == 0)
889                 snprintf(buf, sizeof(buf), "0x%s", val);
890         return strdup(buf);
891 }
892
893 static const char *print_promiscuous(const char *val)
894 {
895         int ival;
896
897         errno = 0;
898         ival = strtol(val, NULL, 10);
899         if (errno) {
900                 char *out;
901                 if (asprintf(&out, "conversion error(%s)", val) < 0)
902                         out = NULL;
903                 return out;
904         }
905
906         if (ival == 0)
907                 return strdup("no");
908         else
909                 return strdup("yes");
910 }
911
912 static const char *print_capabilities(const char *val, int base)
913 {
914         int cap;
915         char *out;
916         const char *s;
917
918         errno = 0;
919         cap = strtoul(val, NULL, base);
920         if (errno) {
921                 if (asprintf(&out, "conversion error(%s)", val) < 0)
922                         out = NULL;
923                 return out;
924         }
925
926         s = cap_i2s(cap);
927         if (s != NULL)
928                 return strdup(s);
929         if (asprintf(&out, "unknown capability(%s%s)",
930                                 base == 16 ? "0x" : "", val) < 0)
931                 out = NULL;
932         return out;
933 }
934
935 static const char *print_cap_bitmap(const char *val)
936 {
937 #define MASK(x) (1U << (x))
938         unsigned long long temp;
939         __u32 caps[2];
940         int i, found=0;
941         char *p, buf[600]; // 17 per cap * 33
942
943         errno = 0;
944         temp = strtoull(val, NULL, 16);
945         if (errno) {
946                 char *out;
947                 if (asprintf(&out, "conversion error(%s)", val) < 0)
948                         out = NULL;
949                 return out;
950         }
951
952         caps[0] =  temp & 0x00000000FFFFFFFFLL;
953         caps[1] = (temp & 0xFFFFFFFF00000000LL) >> 32;
954         p = buf;
955         for (i=0; i <= CAP_LAST_CAP; i++) {
956                 if (MASK(i%32) & caps[i/32]) {
957                         const char *s;
958                         if (found)
959                                 p = stpcpy(p, ",");
960                         s = cap_i2s(i);
961                         if (s != NULL)
962                                 p = stpcpy(p, s);
963                         found = 1;
964                 }
965         }
966         if (found == 0)
967                 return strdup("none");
968         return strdup(buf);
969 }
970
971 static const char *print_success(const char *val)
972 {
973         int res;
974
975         if (isdigit(*val)) {
976                 errno = 0;
977                 res = strtoul(val, NULL, 10);
978                 if (errno) {
979                         char *out;
980                         if (asprintf(&out, "conversion error(%s)", val) < 0)
981                                 out = NULL;
982                         return out;
983                 }
984
985                 return strdup(aulookup_success(res));
986         } else
987                 return strdup(val);
988 }
989
990 static const char *print_open_flags(const char *val)
991 {
992         size_t i;
993         unsigned int flags;
994         int cnt = 0;
995         char *out, buf[178];
996
997         errno = 0;
998         flags = strtoul(val, NULL, 16);
999         if (errno) {
1000                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1001                         out = NULL;
1002                 return out;
1003         }
1004
1005         buf[0] = 0;
1006         if ((flags & O_ACCMODE) == 0) {
1007                 // Handle O_RDONLY specially
1008                 strcat(buf, "O_RDONLY");
1009                 cnt++;
1010         }
1011         for (i=0; i<OPEN_FLAG_NUM_ENTRIES; i++) {
1012                 if (open_flag_table[i].value & flags) {
1013                         if (!cnt) {
1014                                 strcat(buf,
1015                                 open_flag_strings + open_flag_table[i].offset);
1016                                 cnt++;
1017                         } else {
1018                                 strcat(buf, "|");
1019                                 strcat(buf,
1020                                 open_flag_strings + open_flag_table[i].offset);
1021                         }
1022                 }
1023         }
1024         if (buf[0] == 0)
1025                 snprintf(buf, sizeof(buf), "0x%s", val);
1026         return strdup(buf);
1027 }
1028
1029 static const char *print_clone_flags(const char *val)
1030 {
1031         unsigned int flags, i, clone_sig;
1032         int cnt = 0;
1033         char *out, buf[362]; // added 10 for signal name
1034
1035         errno = 0;
1036         flags = strtoul(val, NULL, 16);
1037         if (errno) {
1038                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1039                         out = NULL;
1040                 return out;
1041         }
1042
1043         buf[0] = 0;
1044         for (i=0; i<CLONE_FLAG_NUM_ENTRIES; i++) {
1045                 if (clone_flag_table[i].value & flags) {
1046                         if (!cnt) {
1047                                 strcat(buf,
1048                         clone_flag_strings + clone_flag_table[i].offset);
1049                                 cnt++;
1050                         } else {
1051                                 strcat(buf, "|");
1052                                 strcat(buf,
1053                         clone_flag_strings + clone_flag_table[i].offset);
1054                         }
1055                 }
1056         }
1057         clone_sig = flags & 0xFF;
1058         if (clone_sig && (clone_sig < 32)) {
1059                 const char *s = signal_i2s(clone_sig);
1060                 if (s != NULL) {
1061                         if (buf[0] != 0) 
1062                                 strcat(buf, "|");
1063                         strcat(buf, s);
1064                 }
1065         }
1066
1067         if (buf[0] == 0)
1068                 snprintf(buf, sizeof(buf), "0x%x", flags);
1069         return strdup(buf);
1070 }
1071
1072 static const char *print_fcntl_cmd(const char *val)
1073 {
1074         char *out;
1075         const char *s;
1076         int cmd;
1077
1078         errno = 0;
1079         cmd = strtoul(val, NULL, 16);
1080         if (errno) {
1081                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1082                         out = NULL;
1083                 return out;
1084         }
1085
1086         s = fcntl_i2s(cmd);
1087         if (s != NULL)
1088                 return strdup(s);
1089         if (asprintf(&out, "unknown fcntl command(%d)", cmd) < 0)
1090                 out = NULL;
1091         return out;
1092 }
1093
1094 static const char *print_epoll_ctl(const char *val)
1095 {
1096         char *out;
1097         const char *s;
1098         int cmd;
1099
1100         errno = 0;
1101         cmd = strtoul(val, NULL, 16);
1102         if (errno) {
1103                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1104                         out = NULL;
1105                 return out;
1106         }
1107
1108         s = epoll_ctl_i2s(cmd);
1109         if (s != NULL)
1110                 return strdup(s);
1111         if (asprintf(&out, "unknown epoll_ctl operation (%d)", cmd) < 0)
1112                 out = NULL;
1113         return out;
1114 }
1115
1116 static const char *print_clock_id(const char *val)
1117 {
1118         int i;
1119         char *out;
1120
1121         errno = 0;
1122         i = strtoul(val, NULL, 16);
1123         if (errno) {
1124                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1125                         out = NULL;
1126                 return out;
1127         }
1128         else if (i < 7) {
1129                 const char *s = clock_i2s(i);
1130                 if (s != NULL)
1131                         return strdup(s);
1132         }
1133         if (asprintf(&out, "unknown clk_id (0x%s)", val) < 0)
1134                 out = NULL;
1135         return out;
1136 }
1137
1138 static const char *print_prot(const char *val, unsigned int is_mmap)
1139 {
1140         unsigned int prot, i;
1141         int cnt = 0, limit;
1142         char buf[144];
1143         char *out;
1144
1145         errno = 0;
1146         prot = strtoul(val, NULL, 16);
1147         if (errno) {
1148                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1149                         out = NULL;
1150                 return out;
1151         }
1152         buf[0] = 0;
1153         if ((prot & 0x07) == 0) {
1154                 // Handle PROT_NONE specially
1155                 strcat(buf, "PROT_NONE");
1156                 return strdup(buf);
1157         }
1158         if (is_mmap)
1159                 limit = 4;
1160         else
1161                 limit = 3;
1162         for (i=0; i<limit; i++) {
1163                 if (prot_table[i].value & prot) {
1164                         if (!cnt) {
1165                                 strcat(buf,
1166                                 prot_strings + prot_table[i].offset);
1167                                 cnt++;
1168                         } else {
1169                                 strcat(buf, "|");
1170                                 strcat(buf,
1171                                 prot_strings + prot_table[i].offset);
1172                         }
1173                 }
1174         }
1175         if (buf[0] == 0)
1176                 snprintf(buf, sizeof(buf), "0x%s", val);
1177         return strdup(buf);
1178 }
1179
1180 static const char *print_mmap(const char *val)
1181 {
1182         unsigned int maps, i;
1183         int cnt = 0;
1184         char buf[176];
1185         char *out;
1186
1187         errno = 0;
1188         maps = strtoul(val, NULL, 16);
1189         if (errno) {
1190                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1191                         out = NULL;
1192                 return out;
1193         }
1194         buf[0] = 0;
1195         if ((maps & 0x0F) == 0) {
1196                 // Handle MAP_FILE specially
1197                 strcat(buf, "MAP_FILE");
1198                 cnt++;
1199         }
1200         for (i=0; i<MMAP_NUM_ENTRIES; i++) {
1201                 if (mmap_table[i].value & maps) {
1202                         if (!cnt) {
1203                                 strcat(buf,
1204                                 mmap_strings + mmap_table[i].offset);
1205                                 cnt++;
1206                         } else {
1207                                 strcat(buf, "|");
1208                                 strcat(buf,
1209                                 mmap_strings + mmap_table[i].offset);
1210                         }
1211                 }
1212         }
1213         if (buf[0] == 0)
1214                 snprintf(buf, sizeof(buf), "0x%s", val);
1215         return strdup(buf);
1216 }
1217
1218 static const char *print_personality(const char *val)
1219 {
1220         int pers, pers2;
1221         char *out;
1222         const char *s;
1223
1224         errno = 0;
1225         pers = strtoul(val, NULL, 16);
1226         if (errno) {
1227                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1228                         out = NULL;
1229                 return out;
1230         }
1231
1232         pers2 = pers & ~ADDR_NO_RANDOMIZE;
1233         s = person_i2s(pers2);
1234         if (s != NULL) {
1235                 if (pers & ADDR_NO_RANDOMIZE) {
1236                         if (asprintf(&out, "%s|~ADDR_NO_RANDOMIZE", s) < 0)
1237                                 out = NULL;
1238                         return out;
1239                 } else
1240                         return strdup(s);
1241         }
1242         if (asprintf(&out, "unknown personality (0x%s)", val) < 0)
1243                 out = NULL;
1244         return out;
1245 }
1246
1247 static const char *print_ptrace(const char *val)
1248 {
1249         int trace;
1250         char *out;
1251         const char *s;
1252
1253         errno = 0;
1254         trace = strtoul(val, NULL, 16);
1255         if (errno) {
1256                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1257                         out = NULL;
1258                 return out;
1259         }
1260
1261         s = ptrace_i2s(trace);
1262         if (s != NULL)
1263                 return strdup(s);
1264         if (asprintf(&out, "unknown ptrace (0x%s)", val) < 0)
1265                 out = NULL;
1266         return out;
1267 }
1268
1269 static const char *print_prctl_opt(const char *val)
1270 {
1271         int opt;
1272         char *out;
1273         const char *s;
1274
1275         errno = 0;
1276         opt = strtoul(val, NULL, 16);
1277         if (errno) {
1278                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1279                         out = NULL;
1280                 return out;
1281         }
1282
1283         s = prctl_opt_i2s(opt);
1284         if (s != NULL)
1285                 return strdup(s);
1286         if (asprintf(&out, "unknown prctl option (0x%s)", val) < 0)
1287                 out = NULL;
1288         return out;
1289 }
1290
1291 static const char *print_mount(const char *val)
1292 {
1293         unsigned int mounts, i;
1294         int cnt = 0;
1295         char buf[334];
1296         char *out;
1297
1298         errno = 0;
1299         mounts = strtoul(val, NULL, 16);
1300         if (errno) {
1301                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1302                         out = NULL;
1303                 return out;
1304         }
1305         buf[0] = 0;
1306         for (i=0; i<MOUNT_NUM_ENTRIES; i++) {
1307                 if (mount_table[i].value & mounts) {
1308                         if (!cnt) {
1309                                 strcat(buf,
1310                                 mount_strings + mount_table[i].offset);
1311                                 cnt++;
1312                         } else {
1313                                 strcat(buf, "|");
1314                                 strcat(buf,
1315                                 mount_strings + mount_table[i].offset);
1316                         }
1317                 }
1318         }
1319         if (buf[0] == 0)
1320                 snprintf(buf, sizeof(buf), "0x%s", val);
1321         return strdup(buf);
1322 }
1323
1324 static const char *print_rlimit(const char *val)
1325 {
1326         int i;
1327         char *out;
1328
1329         errno = 0;
1330         i = strtoul(val, NULL, 16);
1331         if (errno) {
1332                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1333                         out = NULL;
1334                 return out;
1335         }
1336         else if (i < 17) {
1337                 const char *s = rlimit_i2s(i);
1338                 if (s != NULL)
1339                         return strdup(s);
1340         }
1341         if (asprintf(&out, "unknown rlimit (0x%s)", val) < 0)
1342                 out = NULL;
1343         return out;
1344 }
1345
1346 static const char *print_recv(const char *val)
1347 {
1348         unsigned int rec, i;
1349         int cnt = 0;
1350         char buf[234];
1351         char *out;
1352
1353         errno = 0;
1354         rec = strtoul(val, NULL, 16);
1355         if (errno) {
1356                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1357                         out = NULL;
1358                 return out;
1359         }
1360         buf[0] = 0;
1361         for (i=0; i<RECV_NUM_ENTRIES; i++) {
1362                 if (recv_table[i].value & rec) {
1363                         if (!cnt) {
1364                                 strcat(buf,
1365                                 recv_strings + recv_table[i].offset);
1366                                 cnt++;
1367                         } else {
1368                                 strcat(buf, "|");
1369                                 strcat(buf,
1370                                 recv_strings + recv_table[i].offset);
1371                         }
1372                 }
1373         }
1374         if (buf[0] == 0)
1375                 snprintf(buf, sizeof(buf), "0x%s", val);
1376         return strdup(buf);
1377 }
1378
1379 static const char *print_access(const char *val)
1380 {
1381         unsigned long mode;
1382         char buf[16];
1383         unsigned int i, cnt = 0;
1384
1385         errno = 0;
1386         mode = strtoul(val, NULL, 16);
1387         if (errno) {
1388                 char *out;
1389                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1390                         out = NULL;
1391                 return out;
1392         }
1393
1394         if ((mode & 0xF) == 0)
1395                 return strdup("F_OK");
1396         buf[0] = 0;
1397         for (i=0; i<3; i++) {
1398                 if (access_table[i].value & mode) {
1399                         if (!cnt) {
1400                                 strcat(buf,
1401                                 access_strings + access_table[i].offset);
1402                                 cnt++;
1403                         } else {
1404                                 strcat(buf, "|");
1405                                 strcat(buf,
1406                                 access_strings + access_table[i].offset);
1407                         }
1408                 }
1409         }
1410         if (buf[0] == 0)
1411                 snprintf(buf, sizeof(buf), "0x%s", val);
1412         return strdup(buf);
1413 }
1414
1415 static char *print_dirfd(const char *val)
1416 {
1417         char *out;
1418
1419         if (strcmp(val, "-100") == 0) {
1420                 if (asprintf(&out, "AT_FDCWD") < 0)
1421                         out = NULL;
1422         } else {
1423                 if (asprintf(&out, "0x%s", val) < 0)
1424                         out = NULL;
1425         }
1426         return out;
1427 }
1428
1429 #ifndef SCHED_RESET_ON_FORK
1430 #define SCHED_RESET_ON_FORK 0x40000000
1431 #endif
1432 static const char *print_sched(const char *val)
1433 {
1434         unsigned int pol;
1435         char *out;
1436         const char *s;
1437
1438         errno = 0;
1439         pol = strtoul(val, NULL, 16);
1440         if (errno) {
1441                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1442                         out = NULL;
1443                 return out;
1444         }
1445
1446         s = sched_i2s(pol & 0x0F);
1447         if (s != NULL) {
1448                 char buf[48];
1449
1450                 strcpy(buf, s);
1451                 if (pol & SCHED_RESET_ON_FORK )
1452                         strcat(buf, "|SCHED_RESET_ON_FORK");
1453                 return strdup(buf);
1454         }
1455         if (asprintf(&out, "unknown scheduler policy (0x%s)", val) < 0)
1456                 out = NULL;
1457         return out;
1458 }
1459
1460 static const char *print_sock_opt_level(const char *val)
1461 {
1462         int lvl;
1463         char *out;
1464
1465         errno = 0;
1466         lvl = strtoul(val, NULL, 16);
1467         if (errno) {
1468                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1469                         out = NULL;
1470                 return out;
1471         }
1472         if (lvl == SOL_SOCKET)
1473                 return strdup("SOL_SOCKET");
1474         else {
1475                 struct protoent *p = getprotobynumber(lvl);
1476                 if (p == NULL) {
1477                         const char *s = socklevel_i2s(lvl);
1478                         if (s != NULL)
1479                                 return strdup(s);
1480                         if (asprintf(&out, "unknown sockopt level (0x%s)", val) < 0)
1481                                 out = NULL;
1482                 } else
1483                         return strdup(p->p_name);
1484         }
1485
1486         return out;
1487 }
1488
1489 static const char *print_sock_opt_name(const char *val, int machine)
1490 {
1491         int opt;
1492         char *out;
1493         const char *s;
1494
1495         errno = 0;
1496         opt = strtoul(val, NULL, 16);
1497         if (errno) {
1498                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1499                         out = NULL;
1500                 return out;
1501         }
1502         // PPC's tables are different
1503         if ((machine == MACH_PPC64 || machine == MACH_PPC) &&
1504                         opt >= 16 && opt <= 21)
1505                 opt+=100;
1506
1507         s = sockoptname_i2s(opt);
1508         if (s != NULL)
1509                 return strdup(s);
1510         if (asprintf(&out, "unknown sockopt name (0x%s)", val) < 0)
1511                 out = NULL;
1512         return out;
1513 }
1514
1515 static const char *print_ip_opt_name(const char *val)
1516 {
1517         int opt;
1518         char *out;
1519         const char *s;
1520
1521         errno = 0;
1522         opt = strtoul(val, NULL, 16);
1523         if (errno) {
1524                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1525                         out = NULL;
1526                 return out;
1527         }
1528
1529         s = ipoptname_i2s(opt);
1530         if (s != NULL)
1531                 return strdup(s);
1532         if (asprintf(&out, "unknown ipopt name (0x%s)", val) < 0)
1533                 out = NULL;
1534         return out;
1535 }
1536
1537 static const char *print_ip6_opt_name(const char *val)
1538 {
1539         int opt;
1540         char *out;
1541         const char *s;
1542
1543         errno = 0;
1544         opt = strtoul(val, NULL, 16);
1545         if (errno) {
1546                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1547                         out = NULL;
1548                 return out;
1549         }
1550
1551         s = ip6optname_i2s(opt);
1552         if (s != NULL)
1553                 return strdup(s);
1554         if (asprintf(&out, "unknown ip6opt name (0x%s)", val) < 0)
1555                 out = NULL;
1556         return out;
1557 }
1558
1559 static const char *print_tcp_opt_name(const char *val)
1560 {
1561         int opt;
1562         char *out;
1563         const char *s;
1564
1565         errno = 0;
1566         opt = strtoul(val, NULL, 16);
1567         if (errno) {
1568                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1569                         out = NULL;
1570                 return out;
1571         }
1572
1573         s = tcpoptname_i2s(opt);
1574         if (s != NULL)
1575                 return strdup(s);
1576         if (asprintf(&out, "unknown tcpopt name (0x%s)", val) < 0)
1577                 out = NULL;
1578         return out;
1579 }
1580
1581 static const char *print_udp_opt_name(const char *val)
1582 {
1583         int opt;
1584         char *out;
1585
1586         errno = 0;
1587         opt = strtoul(val, NULL, 16);
1588         if (errno) {
1589                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1590                         out = NULL;
1591                 return out;
1592         }
1593
1594         if (opt == 1)
1595                 out = strdup("UDP_CORK");
1596         else if (opt == 100)
1597                 out = strdup("UDP_ENCAP");
1598         else if (asprintf(&out, "unknown udpopt name (0x%s)", val) < 0)
1599                 out = NULL;
1600         return out;
1601 }
1602
1603 static const char *print_pkt_opt_name(const char *val)
1604 {
1605         int opt;
1606         char *out;
1607         const char *s;
1608
1609         errno = 0;
1610         opt = strtoul(val, NULL, 16);
1611         if (errno) {
1612                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1613                         out = NULL;
1614                 return out;
1615         }
1616
1617         s = pktoptname_i2s(opt);
1618         if (s != NULL)
1619                 return strdup(s);
1620         if (asprintf(&out, "unknown pktopt name (0x%s)", val) < 0)
1621                 out = NULL;
1622         return out;
1623 }
1624
1625 static const char *print_shmflags(const char *val)
1626 {
1627         unsigned int flags, partial, i;
1628         int cnt = 0;
1629         char *out, buf[32];
1630
1631         errno = 0;
1632         flags = strtoul(val, NULL, 16);
1633         if (errno) {
1634                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1635                         out = NULL;
1636                 return out;
1637         }
1638
1639         partial = flags & 00003000;
1640         buf[0] = 0;
1641         for (i=0; i<IPCCMD_NUM_ENTRIES; i++) {
1642                 if (ipccmd_table[i].value & partial) {
1643                         if (!cnt) {
1644                                 strcat(buf,
1645                         ipccmd_strings + ipccmd_table[i].offset);
1646                                 cnt++;
1647                         } else {
1648                                 strcat(buf, "|");
1649                                 strcat(buf,
1650                         ipccmd_strings + ipccmd_table[i].offset);
1651                         }
1652                 }
1653         }
1654
1655         partial = flags & 00014000;
1656         for (i=0; i<SHM_MODE_NUM_ENTRIES; i++) {
1657                 if (shm_mode_table[i].value & partial) {
1658                         if (!cnt) {
1659                                 strcat(buf,
1660                         shm_mode_strings + shm_mode_table[i].offset);
1661                                 cnt++;
1662                         } else {
1663                                 strcat(buf, "|");
1664                                 strcat(buf,
1665                         shm_mode_strings + shm_mode_table[i].offset);
1666                         }
1667                 }
1668         }
1669
1670         partial = flags & 000777;
1671         const char *tmode = print_mode_short_int(partial);
1672         if (tmode) {
1673                 if (buf[0] != 0)
1674                         strcat(buf, "|");
1675                 strcat(buf, tmode);
1676                 free((void *)tmode);
1677         }
1678
1679         if (buf[0] == 0)
1680                 snprintf(buf, sizeof(buf), "0x%x", flags);
1681         return strdup(buf);
1682 }
1683
1684 static const char *print_seek(const char *val)
1685 {
1686         unsigned int whence;
1687         char *out;
1688         const char *str;
1689
1690         errno = 0;
1691         whence = 0xFF & strtoul(val, NULL, 16);
1692         if (errno) {
1693                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1694                         out = NULL;
1695                 return out;
1696         }
1697         str = seek_i2s(whence);
1698         if (str == NULL) {
1699                 if (asprintf(&out, "unknown whence(%s)", val) < 0)
1700                         out = NULL;
1701                 return out;
1702         } else
1703                 return strdup(str);
1704 }
1705
1706 static const char *print_umount(const char *val)
1707 {
1708         unsigned int flags, i;
1709         int cnt = 0;
1710         char buf[64];
1711         char *out;
1712
1713         errno = 0;
1714         flags = strtoul(val, NULL, 16);
1715         if (errno) {
1716                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1717                         out = NULL;
1718                 return out;
1719         }
1720         buf[0] = 0;
1721         for (i=0; i<UMOUNT_NUM_ENTRIES; i++) {
1722                 if (umount_table[i].value & flags) {
1723                         if (!cnt) {
1724                                 strcat(buf,
1725                                 umount_strings + umount_table[i].offset);
1726                                 cnt++;
1727                         } else {
1728                                 strcat(buf, "|");
1729                                 strcat(buf,
1730                                 umount_strings + umount_table[i].offset);
1731                         }
1732                 }
1733         }
1734         if (buf[0] == 0)
1735                 snprintf(buf, sizeof(buf), "0x%s", val);
1736         return strdup(buf);
1737 }
1738
1739 static const char *print_ioctl_req(const char *val)
1740 {
1741         int req;
1742         char *out;
1743         const char *r;
1744
1745         errno = 0;
1746         req = strtoul(val, NULL, 16);
1747         if (errno) {
1748                 if (asprintf(&out, "conversion error(%s)", val) < 0)
1749                         out = NULL;
1750                 return out;
1751         }
1752
1753         r = ioctlreq_i2s(req);
1754         if (r != NULL)
1755                 return strdup(r);
1756         if (asprintf(&out, "0x%s", val) < 0)
1757                 out = NULL;
1758         return out;
1759 }
1760
1761 static const char *print_a0(const char *val, const idata *id)
1762 {
1763         char *out;
1764         int machine = id->machine, syscall = id->syscall;
1765         const char *sys = audit_syscall_to_name(syscall, machine);
1766         if (sys) {
1767                 if (*sys == 'r') {
1768                         if (strcmp(sys, "rt_sigaction") == 0)
1769                                 return print_signals(val, 16);
1770                         else if (strcmp(sys, "renameat") == 0)
1771                                 return print_dirfd(val);
1772                         else if (strcmp(sys, "readlinkat") == 0)
1773                                 return print_dirfd(val);
1774                 } else if (*sys == 'c') {
1775                         if (strcmp(sys, "clone") == 0)
1776                                 return print_clone_flags(val);
1777                         else if (strcmp(sys, "clock_settime") == 0)
1778                                 return print_clock_id(val);
1779                 } else if (*sys == 'p') {
1780                         if (strcmp(sys, "personality") == 0)
1781                                 return print_personality(val);
1782                         else if (strcmp(sys, "ptrace") == 0)
1783                                 return print_ptrace(val);
1784                         else if (strcmp(sys, "prctl") == 0)
1785                                 return print_prctl_opt(val);
1786                 } else if (*sys == 'm') {
1787                         if (strcmp(sys, "mkdirat") == 0)
1788                                 return print_dirfd(val);
1789                         else if (strcmp(sys, "mknodat") == 0)
1790                                 return print_dirfd(val);
1791                 } else if (*sys == 'f') {
1792                         if (strcmp(sys, "fchownat") == 0)
1793                                 return print_dirfd(val);
1794                         else if (strcmp(sys, "futimesat") == 0)
1795                                 return print_dirfd(val);
1796                         else if (strcmp(sys, "fchmodat") == 0)
1797                                 return print_dirfd(val);
1798                         else if (strcmp(sys, "faccessat") == 0)
1799                                 return print_dirfd(val);
1800                         else if (strcmp(sys, "futimensat") == 0)
1801                                 return print_dirfd(val);
1802                 } else if (*sys == 'u') {
1803                         if (strcmp(sys, "unshare") == 0)
1804                                 return print_clone_flags(val);
1805                         else if (strcmp(sys, "unlinkat") == 0)
1806                                 return print_dirfd(val);
1807                         else if (strcmp(sys, "utimensat") == 0)
1808                                 return print_dirfd(val);
1809                 } else if (strcmp(sys+1, "etrlimit") == 0)
1810                         return print_rlimit(val);
1811                 else if (*sys == 's') {
1812                         if (strcmp(sys, "setuid") == 0)
1813                                 return print_uid(val, 16);
1814                         else if (strcmp(sys, "setreuid") == 0)
1815                                 return print_uid(val, 16);
1816                         else if (strcmp(sys, "setresuid") == 0)
1817                                 return print_uid(val, 16);
1818                         else if (strcmp(sys, "setfsuid") == 0)
1819                                 return print_uid(val, 16);
1820                         else if (strcmp(sys, "setgid") == 0)
1821                                 return print_gid(val, 16);
1822                         else if (strcmp(sys, "setregid") == 0)
1823                                 return print_gid(val, 16);
1824                         else if (strcmp(sys, "setresgid") == 0)
1825                                 return print_gid(val, 16);
1826                         else if (strcmp(sys, "socket") == 0)
1827                                 return print_socket_domain(val);
1828                         else if (strcmp(sys, "setfsgid") == 0)
1829                                 return print_gid(val, 16);
1830                         else if (strcmp(sys, "socketcall") == 0)
1831                                 return print_socketcall(val, 16);
1832                 }
1833                 else if (strcmp(sys, "linkat") == 0)
1834                         return print_dirfd(val);
1835                 else if (strcmp(sys, "newfstatat") == 0)
1836                         return print_dirfd(val);
1837                 else if (strcmp(sys, "openat") == 0)
1838                         return print_dirfd(val);
1839                 else if (strcmp(sys, "ipccall") == 0)
1840                         return print_ipccall(val, 16);
1841         }
1842         if (asprintf(&out, "0x%s", val) < 0)
1843                         out = NULL;
1844         return out;
1845 }
1846
1847 static const char *print_a1(const char *val, const idata *id)
1848 {
1849         char *out;
1850         int machine = id->machine, syscall = id->syscall;
1851         const char *sys = audit_syscall_to_name(syscall, machine);
1852         if (sys) {
1853                 if (*sys == 'f') {
1854                         if (strcmp(sys, "fchmod") == 0)
1855                                 return print_mode_short(val, 16);
1856                         else if (strncmp(sys, "fcntl", 5) == 0)
1857                                 return print_fcntl_cmd(val);
1858                 } else if (*sys == 'c') {
1859                         if (strcmp(sys, "chmod") == 0)
1860                                 return print_mode_short(val, 16);
1861                         else if (strstr(sys, "chown"))
1862                                 return print_uid(val, 16);
1863                         else if (strcmp(sys, "creat") == 0)
1864                                 return print_mode_short(val, 16);
1865                 }
1866                 if (strcmp(sys+1, "etsockopt") == 0)
1867                         return print_sock_opt_level(val);
1868                 else if (*sys == 's') {
1869                         if (strcmp(sys, "setreuid") == 0)
1870                                 return print_uid(val, 16);
1871                         else if (strcmp(sys, "setresuid") == 0)
1872                                 return print_uid(val, 16);
1873                         else if (strcmp(sys, "setregid") == 0)
1874                                 return print_gid(val, 16);
1875                         else if (strcmp(sys, "setresgid") == 0)
1876                                 return print_gid(val, 16);
1877                         else if (strcmp(sys, "socket") == 0)
1878                                 return print_socket_type(val);
1879                         else if (strcmp(sys, "setns") == 0)
1880                                 return print_clone_flags(val);
1881                         else if (strcmp(sys, "sched_setscheduler") == 0)
1882                                 return print_sched(val);
1883                 } else if (*sys == 'm') {
1884                         if (strcmp(sys, "mkdir") == 0)
1885                                 return print_mode_short(val, 16);
1886                         else if (strcmp(sys, "mknod") == 0)
1887                                 return print_mode(val, 16);
1888                         else if (strcmp(sys, "mq_open") == 0)
1889                                 return print_open_flags(val);
1890                 }
1891                 else if (strcmp(sys, "open") == 0)
1892                         return print_open_flags(val);
1893                 else if (strcmp(sys, "access") == 0)
1894                         return print_access(val);
1895                 else if (strcmp(sys, "epoll_ctl") == 0)
1896                         return print_epoll_ctl(val);
1897                 else if (strcmp(sys, "kill") == 0)
1898                         return print_signals(val, 16);
1899                 else if (strcmp(sys, "prctl") == 0) {
1900                         if (id->a0 == PR_CAPBSET_READ ||
1901                                 id->a0 == PR_CAPBSET_DROP)
1902                                 return print_capabilities(val, 16);
1903                         else if (id->a0 == PR_SET_PDEATHSIG)
1904                                 return print_signals(val, 16);
1905                 }
1906                 else if (strcmp(sys, "tkill") == 0)
1907                         return print_signals(val, 16);
1908                 else if (strcmp(sys, "umount2") == 0)
1909                         return print_umount(val);
1910                 else if (strcmp(sys, "ioctl") == 0)
1911                         return print_ioctl_req(val);
1912         }
1913         if (asprintf(&out, "0x%s", val) < 0)
1914                         out = NULL;
1915         return out;
1916 }
1917
1918 static const char *print_a2(const char *val, const idata *id)
1919 {
1920         char *out;
1921         int machine = id->machine, syscall = id->syscall;
1922         const char *sys = audit_syscall_to_name(syscall, machine);
1923         if (sys) {
1924                 if (strncmp(sys, "fcntl", 5) == 0) {
1925                         int ival;
1926
1927                         errno = 0;
1928                         ival = strtoul(val, NULL, 16);
1929                         if (errno) {
1930                                 if (asprintf(&out, "conversion error(%s)",
1931                                              val) < 0)
1932                                         out = NULL;
1933                                 return out;
1934                         }
1935                         switch (id->a1)
1936                         {
1937                                 case F_SETOWN:
1938                                         return print_uid(val, 16);
1939                                 case F_SETFD:
1940                                         if (ival == FD_CLOEXEC)
1941                                                 return strdup("FD_CLOEXEC");
1942                                         /* Fall thru okay. */
1943                                 case F_SETFL:
1944                                 case F_SETLEASE:
1945                                 case F_GETLEASE:
1946                                 case F_NOTIFY:
1947                                         break;
1948                         }
1949                 } else if (strcmp(sys+1, "etsockopt") == 0) {
1950                         if (id->a1 == IPPROTO_IP)
1951                                 return print_ip_opt_name(val);
1952                         else if (id->a1 == SOL_SOCKET)
1953                                 return print_sock_opt_name(val, machine);
1954                         else if (id->a1 == IPPROTO_TCP)
1955                                 return print_tcp_opt_name(val);
1956                         else if (id->a1 == IPPROTO_UDP)
1957                                 return print_udp_opt_name(val);
1958                         else if (id->a1 == IPPROTO_IPV6)
1959                                 return print_ip6_opt_name(val);
1960                         else if (id->a1 == SOL_PACKET)
1961                                 return print_pkt_opt_name(val);
1962                         else
1963                                 goto normal;
1964                 } else if (*sys == 'o') {
1965                         if (strcmp(sys, "openat") == 0)
1966                                 return print_open_flags(val);
1967                         if ((strcmp(sys, "open") == 0) && (id->a1 & O_CREAT))
1968                                 return print_mode_short(val, 16);
1969                 } else if (*sys == 'f') {
1970                         if (strcmp(sys, "fchmodat") == 0)
1971                                 return print_mode_short(val, 16);
1972                         else if (strcmp(sys, "faccessat") == 0)
1973                                 return print_access(val);
1974                 } else if (*sys == 's') {
1975                         if (strcmp(sys, "setresuid") == 0)
1976                                 return print_uid(val, 16);
1977                         else if (strcmp(sys, "setresgid") == 0)
1978                                 return print_gid(val, 16);
1979                         else if (strcmp(sys, "socket") == 0)
1980                                 return print_socket_proto(val);
1981                         else if (strcmp(sys, "sendmsg") == 0)
1982                                 return print_recv(val);
1983                         else if (strcmp(sys, "shmget") == 0)
1984                                 return print_shmflags(val);
1985                 } else if (*sys == 'm') {
1986                         if (strcmp(sys, "mmap") == 0)
1987                                 return print_prot(val, 1);
1988                         else if (strcmp(sys, "mkdirat") == 0)
1989                                 return print_mode_short(val, 16);
1990                         else if (strcmp(sys, "mknodat") == 0)
1991                                 return print_mode_short(val, 16);
1992                         else if (strcmp(sys, "mprotect") == 0)
1993                                 return print_prot(val, 0);
1994                         else if ((strcmp(sys, "mq_open") == 0) &&
1995                                                 (id->a1 & O_CREAT))
1996                                 return print_mode_short(val, 16);
1997                 } else if (*sys == 'r') {
1998                         if (strcmp(sys, "recvmsg") == 0)
1999                                 return print_recv(val);
2000                         else if (strcmp(sys, "readlinkat") == 0)
2001                                 return print_dirfd(val);
2002                 } else if (*sys == 'l') {
2003                         if (strcmp(sys, "linkat") == 0)
2004                                 return print_dirfd(val);
2005                         else if (strcmp(sys, "lseek") == 0)
2006                                 return print_seek(val);
2007                 }
2008                 else if (strstr(sys, "chown"))
2009                         return print_gid(val, 16);
2010                 else if (strcmp(sys, "tgkill") == 0)
2011                         return print_signals(val, 16);
2012         }
2013 normal:
2014         if (asprintf(&out, "0x%s", val) < 0)
2015                         out = NULL;
2016         return out;
2017 }
2018
2019 static const char *print_a3(const char *val, const idata *id)
2020 {
2021         char *out;
2022         int machine = id->machine, syscall = id->syscall;
2023         const char *sys = audit_syscall_to_name(syscall, machine);
2024         if (sys) {
2025                 if (*sys == 'm') {
2026                         if (strcmp(sys, "mmap") == 0)
2027                                 return print_mmap(val);
2028                         else if (strcmp(sys, "mount") == 0)
2029                                 return print_mount(val);
2030                 } else if (*sys == 'r') {
2031                         if (strcmp(sys, "recv") == 0)
2032                                 return print_recv(val);
2033                         else if (strcmp(sys, "recvfrom") == 0)
2034                                 return print_recv(val);
2035                         else if (strcmp(sys, "recvmmsg") == 0)
2036                                 return print_recv(val);
2037                 } else if (*sys == 's') {
2038                         if (strcmp(sys, "send") == 0)
2039                                 return print_recv(val);
2040                         else if (strcmp(sys, "sendto") == 0)
2041                                 return print_recv(val);
2042                         else if (strcmp(sys, "sendmmsg") == 0)
2043                                 return print_recv(val);
2044                 }
2045         }
2046         if (asprintf(&out, "0x%s", val) < 0)
2047                         out = NULL;
2048         return out;
2049 }
2050
2051 static const char *print_signals(const char *val, unsigned int base)
2052 {
2053         int i;
2054         char *out;
2055
2056         errno = 0;
2057         i = strtoul(val, NULL, base);
2058         if (errno) {
2059                 if (asprintf(&out, "conversion error(%s)", val) < 0)
2060                         out = NULL;
2061                 return out;
2062         }
2063         else if (i < 32) {
2064                 const char *s = signal_i2s(i);
2065                 if (s != NULL)
2066                         return strdup(s);
2067         }
2068         if (asprintf(&out, "unknown signal (%s%s)",
2069                                         base == 16 ? "0x" : "", val) < 0)
2070                 out = NULL;
2071         return out;
2072 }
2073
2074 static const char *print_nfproto(const char *val)
2075 {
2076         int proto;
2077         char *out;
2078         const char *s;
2079
2080         errno = 0;
2081         proto = strtoul(val, NULL, 10);
2082         if (errno) {
2083                 if (asprintf(&out, "conversion error(%s)", val) < 0)
2084                         out = NULL;
2085                 return out;
2086         }
2087
2088         s = nfproto_i2s(proto);
2089         if (s != NULL)
2090                 return strdup(s);
2091         if (asprintf(&out, "unknown netfilter protocol (%s)", val) < 0)
2092                 out = NULL;
2093         return out;
2094 }
2095
2096 static const char *print_icmptype(const char *val)
2097 {
2098         int icmptype;
2099         char *out;
2100         const char *s;
2101
2102         errno = 0;
2103         icmptype = strtoul(val, NULL, 10);
2104         if (errno) {
2105                 if (asprintf(&out, "conversion error(%s)", val) < 0)
2106                         out = NULL;
2107                 return out;
2108         }
2109
2110         s = icmptype_i2s(icmptype);
2111         if (s != NULL)
2112                 return strdup(s);
2113         if (asprintf(&out, "unknown icmp type (%s)", val) < 0)
2114                 out = NULL;
2115         return out;
2116 }
2117
2118 static const char *print_protocol(const char *val)
2119 {
2120         int i;
2121         char *out;
2122
2123         errno = 0;
2124         i = strtoul(val, NULL, 10);
2125         if (errno) { 
2126                 if (asprintf(&out, "conversion error(%s)", val) < 0)
2127                         out = NULL;
2128         } else {
2129                 struct protoent *p = getprotobynumber(i);
2130                 if (p)
2131                         out = strdup(p->p_name);
2132                 else
2133                         out = strdup("undefined protocol");
2134         }
2135         return out;
2136 }
2137
2138 static const char *print_addr(const char *val)
2139 {
2140         char *out = strdup(val);
2141         return out;
2142 }
2143
2144 static const char *print_list(const char *val)
2145 {
2146         int i;
2147         char *out;
2148
2149         errno = 0;
2150         i = strtoul(val, NULL, 10);
2151         if (errno) { 
2152                 if (asprintf(&out, "conversion error(%s)", val) < 0)
2153                         out = NULL;
2154         } else
2155                 out = strdup(audit_flag_to_name(i));
2156         return out;
2157 }
2158
2159 struct string_buf {
2160         char *buf; /* NULL if was ever out of memory */
2161         size_t allocated;
2162         size_t pos;
2163 };
2164
2165 /* Append c to buf. */
2166 static void append_char(struct string_buf *buf, char c)
2167 {
2168         if (buf->buf == NULL)
2169                 return;
2170         if (buf->pos == buf->allocated) {
2171                 char *p;
2172
2173                 buf->allocated *= 2;
2174                 p = realloc(buf->buf, buf->allocated);
2175                 if (p == NULL) {
2176                         free(buf->buf);
2177                         buf->buf = NULL;
2178                         return;
2179                 }
2180                 buf->buf = p;
2181         }
2182         buf->buf[buf->pos] = c;
2183         buf->pos++;
2184 }
2185
2186 /* Represent c as a character within a quoted string, and append it to buf. */
2187 static void tty_append_printable_char(struct string_buf *buf, unsigned char c)
2188 {
2189         if (c < 0x20 || c > 0x7E) {
2190                 append_char(buf, '\\');
2191                 append_char(buf, '0' + ((c >> 6) & 07));
2192                 append_char(buf, '0' + ((c >> 3) & 07));
2193                 append_char(buf, '0' + (c & 07));
2194         } else {
2195                 if (c == '\\' || c ==  '"')
2196                         append_char(buf, '\\');
2197                 append_char(buf, c);
2198         }
2199 }
2200
2201 /* Search for a name of a sequence of TTY bytes.
2202    If found, return the name and advance *INPUT.  Return NULL otherwise. */
2203 static const char *tty_find_named_key(unsigned char **input, size_t input_len)
2204 {
2205         /* NUL-terminated list of (sequence, NUL, name, NUL) entries.
2206            First match wins, even if a longer match were possible later */
2207         static const unsigned char named_keys[] =
2208 #define E(SEQ, NAME) SEQ "\0" NAME "\0"
2209 #include "tty_named_keys.h"
2210 #undef E
2211                 "\0";
2212
2213         unsigned char *src;
2214         const unsigned char *nk;
2215
2216         src = *input;
2217         if (*src >= ' ' && (*src < 0x7F || *src >= 0xA0))
2218                 return NULL; /* Fast path */
2219         nk = named_keys;
2220         do {
2221                 const unsigned char *p;
2222                 size_t nk_len;
2223
2224                 p = strchr(nk, '\0');
2225                 nk_len = p - nk;
2226                 if (nk_len <= input_len && memcmp(src, nk, nk_len) == 0) {
2227                         *input += nk_len;
2228                         return p + 1;
2229                 }
2230                 nk = strchr(p + 1, '\0') + 1;
2231         } while (*nk != '\0');
2232         return NULL;
2233 }
2234
2235 static const char *print_tty_data(const char *raw_data)
2236 {
2237         struct string_buf buf;
2238         int in_printable;
2239         unsigned char *data, *data_pos, *data_end;
2240
2241         if (!is_hex_string(raw_data))
2242                 return strdup(raw_data);
2243         data = au_unescape((char *)raw_data);
2244         if (data == NULL)
2245                 return NULL;
2246         data_end = data + strlen(raw_data) / 2;
2247
2248         buf.allocated = 10;
2249         buf.buf = malloc(buf.allocated); /* NULL handled in append_char() */
2250         buf.pos = 0;
2251         in_printable = 0;
2252         data_pos = data;
2253         while (data_pos < data_end) {
2254                 /* FIXME: Unicode */
2255                 const char *desc;
2256
2257                 desc = tty_find_named_key(&data_pos, data_end - data_pos);
2258                 if (desc != NULL) {
2259                         if (in_printable != 0) {
2260                                 append_char(&buf, '"');
2261                                 in_printable = 0;
2262                         }
2263                         if (buf.pos != 0)
2264                                 append_char(&buf, ',');
2265                         append_char(&buf, '<');
2266                         while (*desc != '\0') {
2267                                 append_char(&buf, *desc);
2268                                 desc++;
2269                         }
2270                         append_char(&buf, '>');
2271                 } else {
2272                         if (in_printable == 0) {
2273                                 if (buf.pos != 0)
2274                                         append_char(&buf, ',');
2275                                 append_char(&buf, '"');
2276                                 in_printable = 1;
2277                         }
2278                         tty_append_printable_char(&buf, *data_pos);
2279                         data_pos++;
2280                 }
2281         }
2282         if (in_printable != 0)
2283                 append_char(&buf, '"');
2284         append_char(&buf, '\0');
2285         free(data);
2286         return buf.buf;
2287 }
2288
2289 static const char *print_session(const char *val)
2290 {
2291         if (strcmp(val, "4294967295") == 0)
2292                 return strdup("unset");
2293         else
2294                 return strdup(val);
2295 }
2296
2297 #define SECCOMP_RET_ACTION      0x7fff0000U
2298 static const char *print_seccomp_code(const char *val)
2299 {
2300         unsigned long code;
2301         char *out;
2302         const char *s;
2303
2304         errno = 0;
2305         code = strtoul(val, NULL, 16);
2306         if (errno) {
2307                 if (asprintf(&out, "conversion error(%s)", val) < 0)
2308                         out = NULL;
2309                 return out;
2310         }
2311         s = seccomp_i2s(code & SECCOMP_RET_ACTION);
2312         if (s != NULL)
2313                 return strdup(s);
2314         if (asprintf(&out, "unknown seccomp code (%s)", val) < 0)
2315                 out = NULL;
2316         return out;
2317 }
2318
2319 int lookup_type(const char *name)
2320 {
2321         int i;
2322
2323         if (type_s2i(name, &i) != 0)
2324                 return i;
2325         return AUPARSE_TYPE_UNCLASSIFIED;
2326 }
2327
2328 const char *interpret(const rnode *r)
2329 {
2330         const nvlist *nv = &r->nv;
2331         int type;
2332         idata id;
2333         nvnode *n;
2334         const char *out;
2335
2336         id.machine = r->machine;
2337         id.syscall = r->syscall;
2338         id.a0 = r->a0;
2339         id.a1 = r->a1;
2340         id.name = nvlist_get_cur_name(nv);
2341         id.val = nvlist_get_cur_val(nv);
2342         type = auparse_interp_adjust_type(r->type, id.name, id.val);
2343
2344         out = auparse_do_interpretation(type, &id);
2345         n = nvlist_get_cur(nv);
2346         n->interp_val = (char *)out;
2347
2348         return out;
2349 }
2350
2351 /* 
2352  * rtype:   the record type
2353  * name:    the current field name
2354  * value:   the current field value
2355  * Returns: field's internal type is returned
2356  */
2357 int auparse_interp_adjust_type(int rtype, const char *name, const char *val)
2358 {
2359         int type;
2360
2361         /* This set of statements overrides or corrects the detection.
2362          * In almost all cases its a double use of a field. */
2363         if (rtype == AUDIT_EXECVE && *name == 'a' && strcmp(name, "argc") &&
2364                         !strstr(name, "_len"))
2365                 type = AUPARSE_TYPE_ESCAPED;
2366         else if (rtype == AUDIT_AVC && strcmp(name, "saddr") == 0)
2367                 type = AUPARSE_TYPE_UNCLASSIFIED;
2368         else if (rtype == AUDIT_USER_TTY && strcmp(name, "msg") == 0)
2369                 type = AUPARSE_TYPE_ESCAPED;
2370         else if (rtype == AUDIT_NETFILTER_PKT && strcmp(name, "saddr") == 0)
2371                 type = AUPARSE_TYPE_ADDR;
2372         else if (strcmp(name, "acct") == 0) {
2373                 if (val[0] == '"')
2374                         type = AUPARSE_TYPE_ESCAPED;
2375                 else if (is_hex_string(val))
2376                         type = AUPARSE_TYPE_ESCAPED;
2377                 else
2378                         type = AUPARSE_TYPE_UNCLASSIFIED;
2379         } else if (rtype == AUDIT_PATH && *name =='f' &&
2380                         strcmp(name, "flags") == 0)
2381                 type = AUPARSE_TYPE_FLAGS;
2382         else if (rtype == AUDIT_MQ_OPEN && strcmp(name, "mode") == 0)
2383                 type = AUPARSE_TYPE_MODE_SHORT;
2384         else if (rtype == AUDIT_CRYPTO_KEY_USER && strcmp(name, "fp") == 0)
2385                 type = AUPARSE_TYPE_UNCLASSIFIED;
2386         else if ((strcmp(name, "id") == 0) &&
2387                 (rtype == AUDIT_ADD_GROUP || rtype == AUDIT_GRP_MGMT ||
2388                         rtype == AUDIT_DEL_GROUP))
2389                 type = AUPARSE_TYPE_GID;
2390         else
2391                 type = lookup_type(name);
2392
2393         return type;
2394 }
2395 hidden_def(auparse_interp_adjust_type)
2396
2397 const char *auparse_do_interpretation(int type, const idata *id)
2398 {
2399         const char *out;
2400         switch(type) {
2401                 case AUPARSE_TYPE_UID:
2402                         out = print_uid(id->val, 10);
2403                         break;
2404                 case AUPARSE_TYPE_GID:
2405                         out = print_gid(id->val, 10);
2406                         break;
2407                 case AUPARSE_TYPE_SYSCALL:
2408                         out = print_syscall(id);
2409                         break;
2410                 case AUPARSE_TYPE_ARCH:
2411                         out = print_arch(id->val, id->machine);
2412                         break;
2413                 case AUPARSE_TYPE_EXIT:
2414                         out = print_exit(id->val);
2415                         break;
2416                 case AUPARSE_TYPE_ESCAPED:
2417                         out = print_escaped(id->val);
2418                         break;
2419                 case AUPARSE_TYPE_PERM:
2420                         out = print_perm(id->val);
2421                         break;
2422                 case AUPARSE_TYPE_MODE:
2423                         out = print_mode(id->val,8);
2424                         break;
2425                 case AUPARSE_TYPE_MODE_SHORT:
2426                         out = print_mode_short(id->val,8);
2427                         break;
2428                 case AUPARSE_TYPE_SOCKADDR:
2429                         out = print_sockaddr(id->val);
2430                         break;
2431                 case AUPARSE_TYPE_FLAGS:
2432                         out = print_flags(id->val);
2433                         break;
2434                 case AUPARSE_TYPE_PROMISC:
2435                         out = print_promiscuous(id->val);
2436                         break;
2437                 case AUPARSE_TYPE_CAPABILITY:
2438                         out = print_capabilities(id->val, 10);
2439                         break;
2440                 case AUPARSE_TYPE_SUCCESS:
2441                         out = print_success(id->val);
2442                         break;
2443                 case AUPARSE_TYPE_A0:
2444                         out = print_a0(id->val, id);
2445                         break;
2446                 case AUPARSE_TYPE_A1:
2447                         out = print_a1(id->val, id);
2448                         break;
2449                 case AUPARSE_TYPE_A2:
2450                         out = print_a2(id->val, id);
2451                         break; 
2452                 case AUPARSE_TYPE_A3:
2453                         out = print_a3(id->val, id);
2454                         break; 
2455                 case AUPARSE_TYPE_SIGNAL:
2456                         out = print_signals(id->val, 10);
2457                         break; 
2458                 case AUPARSE_TYPE_LIST:
2459                         out = print_list(id->val);
2460                         break;
2461                 case AUPARSE_TYPE_TTY_DATA:
2462                         out = print_tty_data(id->val);
2463                         break;
2464                 case AUPARSE_TYPE_SESSION:
2465                         out = print_session(id->val);
2466                         break;
2467                 case AUPARSE_TYPE_CAP_BITMAP:
2468                         out = print_cap_bitmap(id->val);
2469                         break;
2470                 case AUPARSE_TYPE_NFPROTO:
2471                         out = print_nfproto(id->val);
2472                         break; 
2473                 case AUPARSE_TYPE_ICMPTYPE:
2474                         out = print_icmptype(id->val);
2475                         break; 
2476                 case AUPARSE_TYPE_PROTOCOL:
2477                         out = print_protocol(id->val);
2478                         break; 
2479                 case AUPARSE_TYPE_ADDR:
2480                         out = print_addr(id->val);
2481                         break;
2482                 case AUPARSE_TYPE_PERSONALITY:
2483                         out = print_personality(id->val);
2484                         break;
2485                 case AUPARSE_TYPE_SECCOMP:
2486                         out = print_seccomp_code(id->val);
2487                         break;
2488                 case AUPARSE_TYPE_OFLAG:
2489                         out = print_open_flags(id->val);
2490                         break;
2491                 case AUPARSE_TYPE_MMAP:
2492                         out = print_mmap(id->val);
2493                         break;
2494                 case AUPARSE_TYPE_PROCTITLE:
2495                         out = print_proctitle(id->val);
2496                         break;
2497                 case AUPARSE_TYPE_MAC_LABEL:
2498                 case AUPARSE_TYPE_UNCLASSIFIED:
2499                 default:
2500                         out = strdup(id->val);
2501                         break;
2502         }
2503
2504         return out;
2505 }
2506 hidden_def(auparse_do_interpretation)
2507