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