b09433c937061801f8d6f5a2f0774dc2046fdeef
[vpp.git] / src / vppinfra / unix-formats.c
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16   Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus
17
18   Permission is hereby granted, free of charge, to any person obtaining
19   a copy of this software and associated documentation files (the
20   "Software"), to deal in the Software without restriction, including
21   without limitation the rights to use, copy, modify, merge, publish,
22   distribute, sublicense, and/or sell copies of the Software, and to
23   permit persons to whom the Software is furnished to do so, subject to
24   the following conditions:
25
26   The above copyright notice and this permission notice shall be
27   included in all copies or substantial portions of the Software.
28
29   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33   LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 */
37
38 #ifdef __KERNEL__
39
40 # include <linux/unistd.h>
41 # include <linux/signal.h>
42
43 #else /* ! __KERNEL__ */
44
45 #define _GNU_SOURCE             /* to get REG_* in ucontext.h */
46 #include <ucontext.h>
47 #undef _GNU_SOURCE
48 #undef __USE_GNU
49
50 #include <unistd.h>
51 #include <signal.h>
52 #include <grp.h>
53
54 #include <time.h>
55 #include <sys/socket.h>
56 #include <netdb.h>
57 #include <math.h>
58
59 #include <vppinfra/time.h>
60
61 #ifdef AF_NETLINK
62 #include <linux/types.h>
63 #include <linux/netlink.h>
64 #endif
65
66 #endif /* ! __KERNEL__ */
67
68
69 #ifdef __KERNEL__
70 # include <linux/socket.h>
71 # include <linux/in.h>
72 # include <linux/ip.h>
73 # include <linux/tcp.h>
74 # include <linux/udp.h>
75 # include <linux/icmp.h>
76 # include <linux/if_ether.h>
77 # include <linux/if_arp.h>
78 #else
79 # include <net/if.h>            /* struct ifnet may live here */
80 # include <netinet/in.h>
81 # include <netinet/ip.h>
82 # include <netinet/tcp.h>
83 # include <netinet/udp.h>
84 # include <netinet/ip_icmp.h>
85 # include <netinet/if_ether.h>
86 #endif /* __KERNEL__ */
87
88 #include <vppinfra/bitops.h> /* foreach_set_bit */
89 #include <vppinfra/format.h>
90 #include <vppinfra/error.h>
91
92 /* Format unix network address family (e.g. AF_INET). */
93 u8 * format_address_family (u8 * s, va_list * va)
94 {
95   uword family = va_arg (*va, uword);
96   u8 * t = (u8 *) "UNKNOWN";
97   switch (family)
98     {
99 #define _(x) case PF_##x: t = (u8 *) #x; break
100       _ (UNSPEC);
101       _ (UNIX);                 /* Unix domain sockets          */
102       _ (INET);                 /* Internet IP Protocol         */
103 #ifdef PF_AX25
104       _ (AX25);                 /* Amateur Radio AX.25          */
105 #endif
106 #ifdef PF_IPX
107       _ (IPX);                  /* Novell IPX                   */
108 #endif
109 #ifdef PF_APPLETALK
110       _ (APPLETALK);            /* AppleTalk DDP                */
111 #endif
112 #ifdef PF_NETROM
113       _ (NETROM);               /* Amateur Radio NET/ROM        */
114 #endif
115 #ifdef PF_BRIDGE
116       _ (BRIDGE);               /* Multiprotocol bridge         */
117 #endif
118 #ifdef PF_ATMPVC
119       _ (ATMPVC);               /* ATM PVCs                     */
120 #endif
121 #ifdef PF_X25
122       _ (X25);                  /* Reserved for X.25 project    */
123 #endif
124 #ifdef PF_INET6
125       _ (INET6);                /* IP version 6                 */
126 #endif
127 #ifdef PF_ROSE
128       _ (ROSE);                 /* Amateur Radio X.25 PLP       */
129 #endif
130 #ifdef PF_DECnet
131       _ (DECnet);               /* Reserved for DECnet project  */
132 #endif
133 #ifdef PF_NETBEUI
134       _ (NETBEUI);              /* Reserved for 802.2LLC project*/
135 #endif
136 #ifdef PF_SECURITY
137       _ (SECURITY);             /* Security callback pseudo AF */
138 #endif
139 #ifdef PF_KEY
140       _ (KEY);                  /* PF_KEY key management API */
141 #endif
142 #ifdef PF_NETLINK
143       _ (NETLINK);
144 #endif
145 #ifdef PF_PACKET
146       _ (PACKET);               /* Packet family                */
147 #endif
148 #ifdef PF_ASH
149       _ (ASH);                  /* Ash                          */
150 #endif
151 #ifdef PF_ECONET
152       _ (ECONET);               /* Acorn Econet                 */
153 #endif
154 #ifdef PF_ATMSVC
155       _ (ATMSVC);               /* ATM SVCs                     */
156 #endif
157 #ifdef PF_SNA
158       _ (SNA);                  /* Linux SNA Project */
159 #endif
160 #ifdef PF_IRDA
161       _ (IRDA);                 /* IRDA sockets                 */
162 #endif
163 #undef _
164     }
165   vec_add (s, t, strlen ((char *) t));
166   return s;
167 }
168
169 u8 * format_network_protocol (u8 * s, va_list * args)
170 {
171   uword family = va_arg (*args, uword);
172   uword protocol = va_arg (*args, uword);
173
174 #ifndef __KERNEL__
175   struct protoent * p = getprotobynumber (protocol);
176
177   ASSERT (family == AF_INET);
178   if (p)
179     return format (s, "%s", p->p_name);
180   else
181     return format (s, "%d", protocol);
182 #else
183   return format (s, "%d/%d", family, protocol);
184 #endif
185 }
186
187 u8 * format_network_port (u8 * s, va_list * args)
188 {
189   uword proto = va_arg (*args, uword);
190   uword port = va_arg (*args, uword);
191
192 #ifndef __KERNEL__
193   struct servent * p = getservbyport (port, proto == IPPROTO_UDP ? "udp" : "tcp");
194
195   if (p)
196     return format (s, "%s", p->s_name);
197   else
198     return format (s, "%d", port);
199 #else
200   return format (s, "%s/%d", proto == IPPROTO_UDP ? "udp" : "tcp", port);
201 #endif
202 }
203
204 /* Format generic network address: takes two arguments family and address.
205    Assumes network byte order. */
206 u8 * format_network_address (u8 * s, va_list * args)
207 {
208   uword family = va_arg (*args, uword);
209   u8 * addr    = va_arg (*args, u8 *);
210
211   switch (family)
212     {
213     case AF_INET:
214       s = format (s, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
215       break;
216
217     case AF_UNSPEC:
218       /* We use AF_UNSPEC for ethernet addresses. */
219       s = format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
220                   addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
221       break;
222
223     default:
224       clib_error ("unsupported address family %d", family);
225     }
226
227   return s;
228 }
229
230 u8 * format_sockaddr (u8 * s, va_list * args)
231 {
232   void * v = va_arg (*args, void *);
233   struct sockaddr * sa = v;
234   static u32 local_counter;
235
236   switch (sa->sa_family)
237     {
238     case AF_INET:
239       {
240         struct sockaddr_in * i = v;
241         s = format (s, "%U:%U",
242                     format_network_address, AF_INET, &i->sin_addr.s_addr,
243                     format_network_port, IPPROTO_TCP, ntohs (i->sin_port));
244       }
245       break;
246
247     case AF_LOCAL:
248       {
249         /* 
250          * There isn't anything useful to print.
251          * The unix cli world uses the output to make a node name,
252          * so we need to return a unique name. 
253          */
254         s = format (s, "local:%u", local_counter++);
255       }
256       break;
257
258 #ifndef __KERNEL__
259 #ifdef AF_NETLINK
260     case AF_NETLINK:
261       {
262         struct sockaddr_nl * n = v;
263         s = format (s, "KERNEL-NETLINK");
264         if (n->nl_groups)
265           s = format (s, " (groups 0x%x)", n->nl_groups);
266         break;
267       }
268 #endif
269 #endif
270
271     default:
272       s = format (s, "sockaddr family %d", sa->sa_family);
273       break;
274     }
275
276   return s;
277 }
278
279 u8 * format_tcp4_packet (u8 * s, va_list * args)
280 {
281   u8 * p = va_arg (*args, u8 *);
282   struct iphdr * ip = (void *) p;
283   struct tcphdr * tcp = (void *) (ip + 1);
284
285   s = format (s, "tcp %U:%U -> %U:%U",
286               format_network_address, AF_INET,  &ip->saddr,
287               format_network_port, IPPROTO_TCP, ntohs (tcp->source),
288               format_network_address, AF_INET,  &ip->daddr,
289               format_network_port, IPPROTO_TCP, ntohs (tcp->dest));
290
291   s = format (s, ", seq 0x%08x -> 0x%08x", tcp->seq, tcp->ack_seq);
292 #define _(f) if (tcp->f) s = format (s, ", " #f);
293   _ (syn); _ (ack); _ (fin); _ (rst); _ (psh); _ (urg);
294 #undef _
295
296   if (tcp->window)
297     s = format (s, ", window 0x%04x", tcp->window);
298   if (tcp->urg)
299     s = format (s, ", urg 0x%04x", tcp->urg_ptr);
300
301   return s;
302 }
303
304 u8 * format_udp4_packet (u8 * s, va_list * args)
305 {
306   u8 * p = va_arg (*args, u8 *);
307   struct iphdr * ip = (void *) p;
308   struct udphdr * udp = (void *) (ip + 1);
309
310   s = format (s, "udp %U:%U -> %U:%U",
311               format_network_address, AF_INET,  &ip->saddr,
312               format_network_port, IPPROTO_UDP, ntohs (udp->source),
313               format_network_address, AF_INET,  &ip->daddr,
314               format_network_port, IPPROTO_UDP, ntohs (udp->dest));
315
316   return s;
317 }
318
319 u8 * format_icmp4_type_and_code (u8 * s, va_list * args)
320 {
321   uword icmp_type = va_arg (*args, uword);
322   uword icmp_code = va_arg (*args, uword);
323
324   switch (icmp_type)
325     {
326 #define _(f,str) case ICMP_##f: s = format (s, str); break;
327       _ (ECHOREPLY, "echo reply");
328       _ (DEST_UNREACH, "unreachable");
329       _ (SOURCE_QUENCH, "source quench");
330       _ (REDIRECT, "redirect");
331       _ (ECHO, "echo request");
332       _ (TIME_EXCEEDED, "time exceeded");
333       _ (PARAMETERPROB, "parameter problem");
334       _ (TIMESTAMP, "timestamp request");
335       _ (TIMESTAMPREPLY, "timestamp reply");
336       _ (INFO_REQUEST, "information request");
337       _ (INFO_REPLY, "information reply");
338       _ (ADDRESS, "address mask request");
339       _ (ADDRESSREPLY, "address mask reply");
340 #undef _
341     default:
342       s = format (s, "unknown type 0x%x", icmp_type);
343     }
344
345   if (icmp_type == ICMP_DEST_UNREACH)
346     {
347       switch (icmp_code)
348         {
349 #define _(f,str) case ICMP_##f: s = format (s, " " # str); break;
350           _ (NET_UNREACH, "network");
351           _ (HOST_UNREACH, "host");
352           _ (PROT_UNREACH, "protocol");
353           _ (PORT_UNREACH, "port");
354           _ (FRAG_NEEDED, ": fragmentation needed/DF set");
355           _ (SR_FAILED, "source route failed");
356           _ (NET_UNKNOWN, "network unknown");
357           _ (HOST_UNKNOWN, "host unknown");
358           _ (HOST_ISOLATED, "host isolated");
359           _ (NET_ANO, "network: admin. prohibited");
360           _ (HOST_ANO, "host: admin. prohibited");
361           _ (NET_UNR_TOS, "network for type-of-service");
362           _ (HOST_UNR_TOS, "host for type-of-service");
363           _ (PKT_FILTERED, ": packet filtered");
364           _ (PREC_VIOLATION, "precedence violation");
365           _ (PREC_CUTOFF, "precedence cut off");
366 #undef _
367         default:
368           s = format (s, "unknown code 0x%x", icmp_code);
369         }
370     }
371   else if (icmp_type == ICMP_REDIRECT)
372     {
373       switch (icmp_code)
374         {
375 #define _(f,str) case ICMP_##f: s = format (s, " " # str); break;
376           _ (REDIR_NET, "network");
377           _ (REDIR_HOST, "host");
378           _ (REDIR_NETTOS, "network for type-of-service");
379           _ (REDIR_HOSTTOS, "host for type-of-service");
380 #undef _
381         default:
382           s = format (s, "unknown code 0x%x", icmp_code);
383         }
384     }
385   else if (icmp_type == ICMP_TIME_EXCEEDED)
386     {
387       switch (icmp_code)
388         {
389 #define _(f,str) case ICMP_##f: s = format (s, " " # str); break;
390           _ (EXC_TTL, "time-to-live zero in transit");
391           _ (EXC_FRAGTIME, "time-to-live zero during reassembly");
392 #undef _
393         default:
394           s = format (s, "unknown code 0x%x", icmp_code);
395         }
396     }
397
398   return s;
399 }
400
401 typedef struct {
402   u8 type;
403   u8 code;
404   u16 checksum;
405 } icmp4_t;
406
407 u8 * format_icmp4_packet (u8 * s, va_list * args)
408 {
409   u8 * p = va_arg (*args, u8 *);
410   struct iphdr * ip = (void *) p;
411   icmp4_t * icmp = (void *) (ip + 1);
412   s = format (s, "icmp %U %U -> %U",
413               format_icmp4_type_and_code, icmp->type, icmp->code,
414               format_network_address, AF_INET,  &ip->saddr,
415               format_network_address, AF_INET,  &ip->daddr);
416
417   return s;
418 }
419
420 u8 * format_ip4_tos_byte (u8 * s, va_list * args)
421 {
422   uword tos = va_arg (*args, uword);
423
424   if (tos & IPTOS_LOWDELAY)
425     s = format (s, "minimize-delay, ");
426   if (tos & IPTOS_MINCOST)
427     s = format (s, "minimize-cost, ");
428   if (tos & IPTOS_THROUGHPUT)
429     s = format (s, "maximize-throughput, ");
430   if (tos & IPTOS_RELIABILITY)
431     s = format (s, "maximize-reliability, ");
432
433   switch (IPTOS_PREC (tos))
434     {
435 #define _(x,y) case IPTOS_PREC_##x: s = format (s, y); break
436       _ (NETCONTROL, "network");
437       _ (INTERNETCONTROL, "internet");
438       _ (CRITIC_ECP, "critical");
439       _ (FLASH, "flash");
440       _ (FLASHOVERRIDE, "flash-override");
441       _ (IMMEDIATE, "immediate");
442       _ (PRIORITY, "priority");
443       _ (ROUTINE, "routine");
444 #undef _
445     }
446
447   return s;
448 }
449
450 u8 * format_ip4_packet (u8 * s, va_list * args)
451 {
452   u8 * p = va_arg (*args, u8 *);
453   struct iphdr * ip = (void *) p;
454
455   static format_function_t * f[256];
456
457   if (! f[IPPROTO_TCP])
458     {
459       f[IPPROTO_TCP] = format_tcp4_packet;
460       f[IPPROTO_UDP] = format_udp4_packet;
461       f[IPPROTO_ICMP] = format_icmp4_packet;
462     }
463
464   if (f[ip->protocol])
465     return format (s, "%U", f[ip->protocol], p);
466
467   s = format (s, "%U: %U -> %U",
468               format_network_protocol, AF_INET, ip->protocol,
469               format_network_address, AF_INET,  &ip->saddr,
470               format_network_address, AF_INET,  &ip->daddr);
471
472   return s;
473 }
474
475 #define foreach_unix_arphrd_type                \
476   _ (NETROM, 0)                                 \
477   _ (ETHER, 1)                                  \
478   _ (EETHER, 2)                                 \
479   _ (AX25, 3)                                   \
480   _ (PRONET, 4)                                 \
481   _ (CHAOS, 5)                                  \
482   _ (IEEE802, 6)                                \
483   _ (ARCNET, 7)                                 \
484   _ (APPLETLK, 8)                               \
485   _ (DLCI, 15)                                  \
486   _ (ATM, 19)                                   \
487   _ (METRICOM, 23)                              \
488   _ (IEEE1394, 24)                              \
489   _ (EUI64, 27)                                 \
490   _ (INFINIBAND, 32)                            \
491   _ (SLIP, 256)                                 \
492   _ (CSLIP, 257)                                \
493   _ (SLIP6, 258)                                \
494   _ (CSLIP6, 259)                               \
495   _ (RSRVD, 260)                                \
496   _ (ADAPT, 264)                                \
497   _ (ROSE, 270)                                 \
498   _ (X25, 271)                                  \
499   _ (HWX25, 272)                                \
500   _ (PPP, 512)                                  \
501   _ (HDLC, 513)                                 \
502   _ (LAPB, 516)                                 \
503   _ (DDCMP, 517)                                \
504   _ (RAWHDLC, 518)                              \
505   _ (TUNNEL, 768)                               \
506   _ (TUNNEL6, 769)                              \
507   _ (FRAD, 770)                                 \
508   _ (SKIP, 771)                                 \
509   _ (LOOPBACK, 772)                             \
510   _ (LOCALTLK, 773)                             \
511   _ (FDDI, 774)                                 \
512   _ (BIF, 775)                                  \
513   _ (SIT, 776)                                  \
514   _ (IPDDP, 777)                                \
515   _ (IPGRE, 778)                                \
516   _ (PIMREG, 779)                               \
517   _ (HIPPI, 780)                                \
518   _ (ASH, 781)                                  \
519   _ (ECONET, 782)                               \
520   _ (IRDA, 783)                                 \
521   _ (FCPP, 784)                                 \
522   _ (FCAL, 785)                                 \
523   _ (FCPL, 786)                                 \
524   _ (FCFABRIC, 787)                             \
525   _ (IEEE802_TR, 800)                           \
526   _ (IEEE80211, 801)                            \
527   _ (IEEE80211_PRISM, 802)                      \
528   _ (IEEE80211_RADIOTAP, 803)                   \
529   _ (VOID, 0xFFFF)                              \
530   _ (NONE, 0xFFFE)
531
532 u8 * format_unix_arphrd (u8 * s, va_list * args)
533 {
534 #ifndef __COVERITY__ /* doesn't understand this at all... */
535   u32 x = va_arg (*args, u32);
536   char * t;
537   switch (x)
538     {
539 #define _(f,n) case ARPHRD_##f: t = #f; break;
540       foreach_unix_arphrd_type
541 #undef _
542     default:
543       t = 0;
544       break;
545     }
546
547   if (t)
548     s = format (s, "%s", t);
549   else
550     s = format (s, "unknown 0x%x", x);
551 #endif
552   return s;
553 }
554
555 #define foreach_unix_interface_flag             \
556   _ (up)                                        \
557   _ (broadcast)                                 \
558   _ (debug)                                     \
559   _ (loopback)                                  \
560   _ (pointopoint)                               \
561   _ (notrailers)                                \
562   _ (running)                                   \
563   _ (noarp)                                     \
564   _ (promisc)                                   \
565   _ (allmulti)                                  \
566   _ (master)                                    \
567   _ (slave)                                     \
568   _ (multicast)                                 \
569   _ (portsel)                                   \
570   _ (automedia)                                 \
571   _ (dynamic)                                   \
572   _ (lower_up)                                  \
573   _ (dormant)                                   \
574   _ (echo)
575
576 static char * unix_interface_flag_names[] = {
577 #define _(f) #f,
578   foreach_unix_interface_flag
579 #undef _
580 };
581
582 u8 * format_unix_interface_flags (u8 * s, va_list * args)
583 {
584   u32 x = va_arg (*args, u32);
585   u32 i;
586
587   if (x == 0)
588     s = format (s, "none");
589   else foreach_set_bit (i, x, ({
590     if (i < ARRAY_LEN (unix_interface_flag_names))
591       s = format (s, "%s", unix_interface_flag_names[i]);
592     else
593       s = format (s, "unknown %d", i);
594     if (x >> (i + 1))
595       s = format (s, ", ");
596   }));
597   return s;
598 }
599
600 typedef struct {
601   u16 ar_hrd;                   /* format of hardware address   */
602   u16 ar_pro;                   /* format of protocol address   */
603   u8  ar_hln;                   /* length of hardware address   */
604   u8  ar_pln;                   /* length of protocol address   */
605   u16 ar_op;                    /* ARP opcode (command)         */
606   u8  ar_sha[6];                /* sender hardware address      */
607   u8  ar_spa[4];                /* sender IP address            */
608   u8  ar_tha[6];                /* target hardware address      */
609   u8  ar_tpa[4];                /* target IP address            */
610 } arp_ether_ip4_t;
611
612 u8 * format_arp_packet (u8 * s, va_list * args)
613 {
614   arp_ether_ip4_t * a = va_arg (*args, arp_ether_ip4_t *);
615   char * op = "unknown";
616
617   if (a->ar_pro != ETH_P_IP ||
618       a->ar_hrd != ARPHRD_ETHER)
619     return s;
620
621   switch (a->ar_op)
622     {
623 #define _(f) case ARPOP_##f: op = #f; break;
624       _ (REQUEST);
625       _ (REPLY);
626       _ (RREQUEST);
627       _ (RREPLY);
628 #undef _
629     }
630
631   s = format (s, "%s %U %U -> %U %U",
632               op,
633               format_network_address, AF_INET,   a->ar_spa,
634               format_network_address, AF_UNSPEC, a->ar_sha,
635               format_network_address, AF_INET,   a->ar_tpa,
636               format_network_address, AF_UNSPEC, a->ar_tha);
637   return s;
638 }
639
640 u8 * format_ethernet_proto (u8 * s, va_list * args)
641 {
642   uword type = va_arg (*args, uword);
643   char * t = 0;
644
645   switch (type)
646     {
647     case 0: t = "BPDU"; break;
648 #define _(f) case ETH_P_##f: t = #f; break;
649       _ (LOOP);
650       _ (PUP);
651 #ifdef ETH_P_PUPAT
652       _ (PUPAT);
653 #endif
654       _ (IP);
655       _ (X25);
656       _ (ARP);
657       _ (BPQ);
658 #ifdef ETH_P_PUPAT
659       _ (IEEEPUP);
660       _ (IEEEPUPAT);
661 #endif
662       _ (DEC);
663       _ (DNA_DL);
664       _ (DNA_RC);
665       _ (DNA_RT);
666       _ (LAT);
667       _ (DIAG);
668       _ (CUST);
669       _ (SCA);
670       _ (RARP);
671       _ (ATALK);
672       _ (AARP);
673       _ (IPX);
674       _ (IPV6);
675 #ifdef ETH_P_PPP_DISC
676       _ (PPP_DISC);
677       _ (PPP_SES);
678 #endif
679 #ifdef ETH_P_ATMMPOA
680       _ (ATMMPOA);
681       _ (ATMFATE);
682 #endif
683       _ (802_3);
684       _ (AX25);
685       _ (ALL);
686       _ (802_2);
687       _ (SNAP);
688       _ (DDCMP);
689       _ (WAN_PPP);
690       _ (PPP_MP);
691       _ (LOCALTALK);
692       _ (PPPTALK);
693       _ (TR_802_2);
694       _ (MOBITEX);
695       _ (CONTROL);
696       _ (IRDA);
697 #ifdef ETH_P_ECONET
698       _ (ECONET);
699 #endif
700 #undef _
701     }
702
703   if (t)
704     vec_add (s, t, strlen (t));
705   else
706     s = format (s, "ether-type 0x%x", type);
707   return s;
708 }
709
710 u8 * format_ethernet_packet (u8 * s, va_list * args)
711 {
712   struct ethhdr * h = va_arg (*args, struct ethhdr *);
713   uword proto = h->h_proto;
714   u8 * payload = (void *) (h + 1);
715   uword indent;
716
717   /* Check for 802.2/802.3 encapsulation. */
718   if (proto < ETH_DATA_LEN)
719     {
720       typedef struct {
721         u8 dsap, ssap, control;
722         u8 orig_code[3];
723         u16 proto;
724       } ethhdr_802_t;
725       ethhdr_802_t * h1 = (void *) (h + 1);
726       proto = h1->proto;
727       payload = (void *) (h1 + 1);
728     }
729
730   indent = format_get_indent (s);
731
732   s = format (s, "%U: %U -> %U",
733               format_ethernet_proto, proto,
734               format_network_address, AF_UNSPEC, h->h_source,
735               format_network_address, AF_UNSPEC, h->h_dest);
736
737   switch (proto)
738     {
739     case ETH_P_ARP:
740       s = format (s, "\n%U%U",
741                   format_white_space, indent,
742                   format_arp_packet, payload);
743       break;
744     }
745
746   return s;
747 }
748
749 #ifndef __KERNEL__
750 u8 * format_hostname (u8 * s, va_list * args)
751 {
752   char buffer[1024];
753   char * b = buffer;
754   if (gethostname (b, sizeof (buffer)) < 0)
755     b = "noname";
756   return format (s, "%s", b);
757 }
758 #endif
759
760 #ifndef __KERNEL__
761 u8 * format_timeval (u8 * s, va_list * args)
762 {
763   char * fmt = va_arg (*args, char *);
764   struct timeval * tv = va_arg (*args, struct timeval *);
765   struct tm * tm;
766   word msec;
767   char * f, c;
768
769   if (! fmt)
770     fmt = "y/m/d H:M:S:F";
771
772   if (! tv)
773     {
774       static struct timeval now;
775       gettimeofday (&now, 0);
776       tv = &now;
777     }
778
779   msec = flt_round_nearest (1e-3 * tv->tv_usec);
780   if (msec >= 1000)
781     { msec = 0; tv->tv_sec++; }
782
783   {
784     time_t t = tv->tv_sec;
785     tm = localtime (&t);
786   }
787
788   for (f = fmt; *f; f++)
789     {
790       uword what;
791       char * what_fmt = "%d";
792
793       switch (c = *f)
794         {
795         default:
796           vec_add1 (s, c);
797           continue;
798
799         case 'y':
800           what = 1900 + tm->tm_year;
801           what_fmt = "%4d";
802           break;
803         case 'm':
804           what = tm->tm_mon + 1;
805           what_fmt = "%2d";
806           break;
807         case 'd':
808           what = tm->tm_mday;
809           what_fmt = "%2d";
810           break;
811         case 'H':
812           what = tm->tm_hour;
813           what_fmt = "%02d";
814           break;
815         case 'M':
816           what = tm->tm_min;
817           what_fmt = "%02d";
818           break;
819         case 'S':
820           what = tm->tm_sec;
821           what_fmt = "%02d";
822           break;
823         case 'F':
824           what = msec;
825           what_fmt = "%03d";
826           break;
827         }
828
829       s = format (s, what_fmt, what);
830     }
831
832   return s;
833 }
834
835 u8 * format_time_float (u8 * s, va_list * args)
836 {
837   u8 * fmt = va_arg (*args, u8 *);
838   f64 t = va_arg (*args, f64);
839   struct timeval tv;
840   if (t <= 0)
841     t = unix_time_now ();
842   tv.tv_sec = t;
843   tv.tv_usec = 1e6*(t - tv.tv_sec);
844   return format (s, "%U", format_timeval, fmt, &tv);
845 }
846
847 u8 * format_signal (u8 * s, va_list * args)
848 {
849   uword signum = va_arg (*args, uword);
850   char * t = 0;
851   switch (signum)
852     {
853 #define _(x) case x: t = #x; break;
854       _ (SIGHUP);
855       _ (SIGINT);
856       _ (SIGQUIT);
857       _ (SIGILL);
858       _ (SIGTRAP);
859       _ (SIGABRT);
860       _ (SIGBUS);
861       _ (SIGFPE);
862       _ (SIGKILL);
863       _ (SIGUSR1);
864       _ (SIGSEGV);
865       _ (SIGUSR2);
866       _ (SIGPIPE);
867       _ (SIGALRM);
868       _ (SIGTERM);
869 #ifdef SIGSTKFLT
870       _ (SIGSTKFLT);
871 #endif
872       _ (SIGCHLD);
873       _ (SIGCONT);
874       _ (SIGSTOP);
875       _ (SIGTSTP);
876       _ (SIGTTIN);
877       _ (SIGTTOU);
878       _ (SIGURG);
879       _ (SIGXCPU);
880       _ (SIGXFSZ);
881       _ (SIGVTALRM);
882       _ (SIGPROF);
883       _ (SIGWINCH);
884       _ (SIGIO);
885       _ (SIGPWR);
886 #ifdef SIGSYS
887       _ (SIGSYS);
888 #endif
889 #undef _
890     default:
891       return format (s, "unknown %d", signum);
892     }
893
894   vec_add (s, t, strlen (t));
895   return s;
896 }
897
898 u8 * format_ucontext_pc (u8 * s, va_list * args)
899 {
900   ucontext_t * uc __attribute__((unused));
901   unsigned long * regs = 0;
902   uword reg_no = 0;
903
904   uc = va_arg (*args, ucontext_t *);
905
906 #if defined (powerpc)
907   regs = &uc->uc_mcontext.uc_regs->gregs[0];
908 #elif defined (powerpc64)
909   regs = &uc->uc_mcontext.uc_regs->gp_regs[0];
910 #elif defined (i386) || defined (__x86_64__)
911   regs = (void *) &uc->uc_mcontext.gregs[0];
912 #endif
913
914 #if defined (powerpc) || defined (powerpc64)
915   reg_no = PT_NIP;
916 #elif defined (i386)
917   reg_no = REG_EIP;
918 #elif defined (__x86_64__)
919   reg_no = REG_RIP;
920 #else
921   reg_no = 0;
922   regs = 0;
923 #endif
924
925   if (! regs)
926     return format (s, "unsupported");
927   else
928     return format (s, "%p", regs[reg_no]);
929 }
930
931 uword
932 unformat_unix_gid (unformat_input_t * input, va_list * args)
933 {
934   gid_t *gid = va_arg (*args, gid_t *);
935   struct group *grp = 0;
936   int r;
937   u8 *s;
938
939   if (unformat (input, "%d", &r))
940     {
941       grp = getgrgid (r);
942     }
943   else if (unformat (input, "%s", &s))
944     {
945       grp = getgrnam ((char *) s);
946       vec_free (s);
947     }
948   if (grp)
949     {
950       *gid = grp->gr_gid;
951       return 1;
952     }
953   return 0;
954 }
955
956 #endif /* __KERNEL__ */