678700e61294bb003645002c382b8127533a01c8
[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   u16 source = udp->uh_sport;
320   u16 dest = udp->uh_dport;
321
322   s = format (s, "udp %U:%U -> %U:%U", format_network_address, AF_INET,
323               &ip->saddr, format_network_port, IPPROTO_UDP, ntohs (source),
324               format_network_address, AF_INET, &ip->daddr, format_network_port,
325               IPPROTO_UDP, ntohs (dest));
326
327   return s;
328 }
329
330 u8 * format_icmp4_type_and_code (u8 * s, va_list * args)
331 {
332   uword icmp_type = va_arg (*args, uword);
333   uword icmp_code = va_arg (*args, uword);
334
335   switch (icmp_type)
336     {
337 #define _(f,str) case ICMP_##f: s = format (s, str); break;
338       _ (ECHOREPLY, "echo reply");
339       _ (DEST_UNREACH, "unreachable");
340       _ (SOURCE_QUENCH, "source quench");
341       _ (REDIRECT, "redirect");
342       _ (ECHO, "echo request");
343       _ (TIME_EXCEEDED, "time exceeded");
344       _ (PARAMETERPROB, "parameter problem");
345       _ (TIMESTAMP, "timestamp request");
346       _ (TIMESTAMPREPLY, "timestamp reply");
347       _ (INFO_REQUEST, "information request");
348       _ (INFO_REPLY, "information reply");
349       _ (ADDRESS, "address mask request");
350       _ (ADDRESSREPLY, "address mask reply");
351 #undef _
352     default:
353       s = format (s, "unknown type 0x%x", icmp_type);
354     }
355
356   if (icmp_type == ICMP_DEST_UNREACH)
357     {
358       switch (icmp_code)
359         {
360 #define _(f,str) case ICMP_##f: s = format (s, " " # str); break;
361           _ (NET_UNREACH, "network");
362           _ (HOST_UNREACH, "host");
363           _ (PROT_UNREACH, "protocol");
364           _ (PORT_UNREACH, "port");
365           _ (FRAG_NEEDED, ": fragmentation needed/DF set");
366           _ (SR_FAILED, "source route failed");
367           _ (NET_UNKNOWN, "network unknown");
368           _ (HOST_UNKNOWN, "host unknown");
369           _ (HOST_ISOLATED, "host isolated");
370           _ (NET_ANO, "network: admin. prohibited");
371           _ (HOST_ANO, "host: admin. prohibited");
372           _ (NET_UNR_TOS, "network for type-of-service");
373           _ (HOST_UNR_TOS, "host for type-of-service");
374           _ (PKT_FILTERED, ": packet filtered");
375           _ (PREC_VIOLATION, "precedence violation");
376           _ (PREC_CUTOFF, "precedence cut off");
377 #undef _
378         default:
379           s = format (s, "unknown code 0x%x", icmp_code);
380         }
381     }
382   else if (icmp_type == ICMP_REDIRECT)
383     {
384       switch (icmp_code)
385         {
386 #define _(f,str) case ICMP_##f: s = format (s, " " # str); break;
387           _ (REDIR_NET, "network");
388           _ (REDIR_HOST, "host");
389           _ (REDIR_NETTOS, "network for type-of-service");
390           _ (REDIR_HOSTTOS, "host for type-of-service");
391 #undef _
392         default:
393           s = format (s, "unknown code 0x%x", icmp_code);
394         }
395     }
396   else if (icmp_type == ICMP_TIME_EXCEEDED)
397     {
398       switch (icmp_code)
399         {
400 #define _(f,str) case ICMP_##f: s = format (s, " " # str); break;
401           _ (EXC_TTL, "time-to-live zero in transit");
402           _ (EXC_FRAGTIME, "time-to-live zero during reassembly");
403 #undef _
404         default:
405           s = format (s, "unknown code 0x%x", icmp_code);
406         }
407     }
408
409   return s;
410 }
411
412 typedef struct {
413   u8 type;
414   u8 code;
415   u16 checksum;
416 } icmp4_t;
417
418 u8 * format_icmp4_packet (u8 * s, va_list * args)
419 {
420   u8 * p = va_arg (*args, u8 *);
421   struct iphdr * ip = (void *) p;
422   icmp4_t * icmp = (void *) (ip + 1);
423   s = format (s, "icmp %U %U -> %U",
424               format_icmp4_type_and_code, icmp->type, icmp->code,
425               format_network_address, AF_INET,  &ip->saddr,
426               format_network_address, AF_INET,  &ip->daddr);
427
428   return s;
429 }
430
431 u8 * format_ip4_tos_byte (u8 * s, va_list * args)
432 {
433   uword tos = va_arg (*args, uword);
434
435   if (tos & IPTOS_LOWDELAY)
436     s = format (s, "minimize-delay, ");
437   if (tos & IPTOS_MINCOST)
438     s = format (s, "minimize-cost, ");
439   if (tos & IPTOS_THROUGHPUT)
440     s = format (s, "maximize-throughput, ");
441   if (tos & IPTOS_RELIABILITY)
442     s = format (s, "maximize-reliability, ");
443
444   switch (IPTOS_PREC (tos))
445     {
446 #define _(x,y) case IPTOS_PREC_##x: s = format (s, y); break
447       _ (NETCONTROL, "network");
448       _ (INTERNETCONTROL, "internet");
449       _ (CRITIC_ECP, "critical");
450       _ (FLASH, "flash");
451       _ (FLASHOVERRIDE, "flash-override");
452       _ (IMMEDIATE, "immediate");
453       _ (PRIORITY, "priority");
454       _ (ROUTINE, "routine");
455 #undef _
456     }
457
458   return s;
459 }
460
461 u8 * format_ip4_packet (u8 * s, va_list * args)
462 {
463   u8 * p = va_arg (*args, u8 *);
464   struct iphdr * ip = (void *) p;
465
466   static format_function_t * f[256];
467
468   if (! f[IPPROTO_TCP])
469     {
470       f[IPPROTO_TCP] = format_tcp4_packet;
471       f[IPPROTO_UDP] = format_udp4_packet;
472       f[IPPROTO_ICMP] = format_icmp4_packet;
473     }
474
475   if (f[ip->protocol])
476     return format (s, "%U", f[ip->protocol], p);
477
478   s = format (s, "%U: %U -> %U",
479               format_network_protocol, AF_INET, ip->protocol,
480               format_network_address, AF_INET,  &ip->saddr,
481               format_network_address, AF_INET,  &ip->daddr);
482
483   return s;
484 }
485
486 #define foreach_unix_arphrd_type                \
487   _ (NETROM, 0)                                 \
488   _ (ETHER, 1)                                  \
489   _ (EETHER, 2)                                 \
490   _ (AX25, 3)                                   \
491   _ (PRONET, 4)                                 \
492   _ (CHAOS, 5)                                  \
493   _ (IEEE802, 6)                                \
494   _ (ARCNET, 7)                                 \
495   _ (APPLETLK, 8)                               \
496   _ (DLCI, 15)                                  \
497   _ (ATM, 19)                                   \
498   _ (METRICOM, 23)                              \
499   _ (IEEE1394, 24)                              \
500   _ (EUI64, 27)                                 \
501   _ (INFINIBAND, 32)                            \
502   _ (SLIP, 256)                                 \
503   _ (CSLIP, 257)                                \
504   _ (SLIP6, 258)                                \
505   _ (CSLIP6, 259)                               \
506   _ (RSRVD, 260)                                \
507   _ (ADAPT, 264)                                \
508   _ (ROSE, 270)                                 \
509   _ (X25, 271)                                  \
510   _ (HWX25, 272)                                \
511   _ (PPP, 512)                                  \
512   _ (HDLC, 513)                                 \
513   _ (LAPB, 516)                                 \
514   _ (DDCMP, 517)                                \
515   _ (RAWHDLC, 518)                              \
516   _ (TUNNEL, 768)                               \
517   _ (TUNNEL6, 769)                              \
518   _ (FRAD, 770)                                 \
519   _ (SKIP, 771)                                 \
520   _ (LOOPBACK, 772)                             \
521   _ (LOCALTLK, 773)                             \
522   _ (FDDI, 774)                                 \
523   _ (BIF, 775)                                  \
524   _ (SIT, 776)                                  \
525   _ (IPDDP, 777)                                \
526   _ (IPGRE, 778)                                \
527   _ (PIMREG, 779)                               \
528   _ (HIPPI, 780)                                \
529   _ (ASH, 781)                                  \
530   _ (ECONET, 782)                               \
531   _ (IRDA, 783)                                 \
532   _ (FCPP, 784)                                 \
533   _ (FCAL, 785)                                 \
534   _ (FCPL, 786)                                 \
535   _ (FCFABRIC, 787)                             \
536   _ (IEEE802_TR, 800)                           \
537   _ (IEEE80211, 801)                            \
538   _ (IEEE80211_PRISM, 802)                      \
539   _ (IEEE80211_RADIOTAP, 803)                   \
540   _ (VOID, 0xFFFF)                              \
541   _ (NONE, 0xFFFE)
542
543 u8 * format_unix_arphrd (u8 * s, va_list * args)
544 {
545 #ifndef __COVERITY__ /* doesn't understand this at all... */
546   u32 x = va_arg (*args, u32);
547   char * t;
548   switch (x)
549     {
550 #define _(f,n) case ARPHRD_##f: t = #f; break;
551       foreach_unix_arphrd_type
552 #undef _
553     default:
554       t = 0;
555       break;
556     }
557
558   if (t)
559     s = format (s, "%s", t);
560   else
561     s = format (s, "unknown 0x%x", x);
562 #endif
563   return s;
564 }
565
566 #define foreach_unix_interface_flag             \
567   _ (up)                                        \
568   _ (broadcast)                                 \
569   _ (debug)                                     \
570   _ (loopback)                                  \
571   _ (pointopoint)                               \
572   _ (notrailers)                                \
573   _ (running)                                   \
574   _ (noarp)                                     \
575   _ (promisc)                                   \
576   _ (allmulti)                                  \
577   _ (master)                                    \
578   _ (slave)                                     \
579   _ (multicast)                                 \
580   _ (portsel)                                   \
581   _ (automedia)                                 \
582   _ (dynamic)                                   \
583   _ (lower_up)                                  \
584   _ (dormant)                                   \
585   _ (echo)
586
587 static char * unix_interface_flag_names[] = {
588 #define _(f) #f,
589   foreach_unix_interface_flag
590 #undef _
591 };
592
593 u8 * format_unix_interface_flags (u8 * s, va_list * args)
594 {
595   u32 x = va_arg (*args, u32);
596   u32 i;
597
598   if (x == 0)
599     s = format (s, "none");
600   else foreach_set_bit (i, x, ({
601     if (i < ARRAY_LEN (unix_interface_flag_names))
602       s = format (s, "%s", unix_interface_flag_names[i]);
603     else
604       s = format (s, "unknown %d", i);
605     if (x >> (i + 1))
606       s = format (s, ", ");
607   }));
608   return s;
609 }
610
611 typedef struct {
612   u16 ar_hrd;                   /* format of hardware address   */
613   u16 ar_pro;                   /* format of protocol address   */
614   u8  ar_hln;                   /* length of hardware address   */
615   u8  ar_pln;                   /* length of protocol address   */
616   u16 ar_op;                    /* ARP opcode (command)         */
617   u8  ar_sha[6];                /* sender hardware address      */
618   u8  ar_spa[4];                /* sender IP address            */
619   u8  ar_tha[6];                /* target hardware address      */
620   u8  ar_tpa[4];                /* target IP address            */
621 } arp_ether_ip4_t;
622
623 u8 * format_arp_packet (u8 * s, va_list * args)
624 {
625   arp_ether_ip4_t * a = va_arg (*args, arp_ether_ip4_t *);
626   char * op = "unknown";
627
628   if (a->ar_pro != ETH_P_IP ||
629       a->ar_hrd != ARPHRD_ETHER)
630     return s;
631
632   switch (a->ar_op)
633     {
634 #define _(f) case ARPOP_##f: op = #f; break;
635       _ (REQUEST);
636       _ (REPLY);
637       _ (RREQUEST);
638       _ (RREPLY);
639 #undef _
640     }
641
642   s = format (s, "%s %U %U -> %U %U",
643               op,
644               format_network_address, AF_INET,   a->ar_spa,
645               format_network_address, AF_UNSPEC, a->ar_sha,
646               format_network_address, AF_INET,   a->ar_tpa,
647               format_network_address, AF_UNSPEC, a->ar_tha);
648   return s;
649 }
650
651 u8 * format_ethernet_proto (u8 * s, va_list * args)
652 {
653   uword type = va_arg (*args, uword);
654   char * t = 0;
655
656   switch (type)
657     {
658     case 0: t = "BPDU"; break;
659 #define _(f) case ETH_P_##f: t = #f; break;
660       _ (LOOP);
661       _ (PUP);
662 #ifdef ETH_P_PUPAT
663       _ (PUPAT);
664 #endif
665       _ (IP);
666       _ (X25);
667       _ (ARP);
668       _ (BPQ);
669 #ifdef ETH_P_PUPAT
670       _ (IEEEPUP);
671       _ (IEEEPUPAT);
672 #endif
673       _ (DEC);
674       _ (DNA_DL);
675       _ (DNA_RC);
676       _ (DNA_RT);
677       _ (LAT);
678       _ (DIAG);
679       _ (CUST);
680       _ (SCA);
681       _ (RARP);
682       _ (ATALK);
683       _ (AARP);
684       _ (IPX);
685       _ (IPV6);
686 #ifdef ETH_P_PPP_DISC
687       _ (PPP_DISC);
688       _ (PPP_SES);
689 #endif
690 #ifdef ETH_P_ATMMPOA
691       _ (ATMMPOA);
692       _ (ATMFATE);
693 #endif
694       _ (802_3);
695       _ (AX25);
696       _ (ALL);
697       _ (802_2);
698       _ (SNAP);
699       _ (DDCMP);
700       _ (WAN_PPP);
701       _ (PPP_MP);
702       _ (LOCALTALK);
703       _ (PPPTALK);
704       _ (TR_802_2);
705       _ (MOBITEX);
706       _ (CONTROL);
707       _ (IRDA);
708 #ifdef ETH_P_ECONET
709       _ (ECONET);
710 #endif
711 #undef _
712     }
713
714   if (t)
715     vec_add (s, t, strlen (t));
716   else
717     s = format (s, "ether-type 0x%x", type);
718   return s;
719 }
720
721 u8 * format_ethernet_packet (u8 * s, va_list * args)
722 {
723   struct ethhdr * h = va_arg (*args, struct ethhdr *);
724   uword proto = h->h_proto;
725   u8 * payload = (void *) (h + 1);
726   u32 indent;
727
728   /* Check for 802.2/802.3 encapsulation. */
729   if (proto < ETH_DATA_LEN)
730     {
731       typedef struct {
732         u8 dsap, ssap, control;
733         u8 orig_code[3];
734         u16 proto;
735       } ethhdr_802_t;
736       ethhdr_802_t * h1 = (void *) (h + 1);
737       proto = h1->proto;
738       payload = (void *) (h1 + 1);
739     }
740
741   indent = format_get_indent (s);
742
743   s = format (s, "%U: %U -> %U",
744               format_ethernet_proto, proto,
745               format_network_address, AF_UNSPEC, h->h_source,
746               format_network_address, AF_UNSPEC, h->h_dest);
747
748   switch (proto)
749     {
750     case ETH_P_ARP:
751       s = format (s, "\n%U%U",
752                   format_white_space, indent,
753                   format_arp_packet, payload);
754       break;
755     }
756
757   return s;
758 }
759
760 #ifndef __KERNEL__
761 u8 * format_hostname (u8 * s, va_list * args)
762 {
763   char buffer[1024];
764   char * b = buffer;
765   if (gethostname (b, sizeof (buffer)) < 0)
766     b = "noname";
767   return format (s, "%s", b);
768 }
769 #endif
770
771 #ifndef __KERNEL__
772 u8 * format_timeval (u8 * s, va_list * args)
773 {
774   char * fmt = va_arg (*args, char *);
775   struct timeval * tv = va_arg (*args, struct timeval *);
776   struct tm * tm;
777   word msec;
778   char * f, c;
779
780   if (! fmt)
781     fmt = "y/m/d H:M:S:F";
782
783   if (! tv)
784     {
785       static struct timeval now;
786       gettimeofday (&now, 0);
787       tv = &now;
788     }
789
790   msec = flt_round_nearest (1e-3 * tv->tv_usec);
791   if (msec >= 1000)
792     { msec = 0; tv->tv_sec++; }
793
794   {
795     time_t t = tv->tv_sec;
796     tm = localtime (&t);
797   }
798
799   for (f = fmt; *f; f++)
800     {
801       uword what;
802       char * what_fmt = "%d";
803
804       switch (c = *f)
805         {
806         default:
807           vec_add1 (s, c);
808           continue;
809
810         case 'y':
811           what = 1900 + tm->tm_year;
812           what_fmt = "%4d";
813           break;
814         case 'm':
815           what = tm->tm_mon + 1;
816           what_fmt = "%02d";
817           break;
818         case 'd':
819           what = tm->tm_mday;
820           what_fmt = "%02d";
821           break;
822         case 'H':
823           what = tm->tm_hour;
824           what_fmt = "%02d";
825           break;
826         case 'M':
827           what = tm->tm_min;
828           what_fmt = "%02d";
829           break;
830         case 'S':
831           what = tm->tm_sec;
832           what_fmt = "%02d";
833           break;
834         case 'F':
835           what = msec;
836           what_fmt = "%03d";
837           break;
838         }
839
840       s = format (s, what_fmt, what);
841     }
842
843   return s;
844 }
845 #endif
846
847 u8 * format_time_float (u8 * s, va_list * args)
848 {
849   u8 * fmt = va_arg (*args, u8 *);
850   f64 t = va_arg (*args, f64);
851   struct timeval tv;
852   if (t <= 0)
853     t = unix_time_now ();
854   tv.tv_sec = t;
855   tv.tv_usec = 1e6*(t - tv.tv_sec);
856   return format (s, "%U", format_timeval, fmt, &tv);
857 }
858
859 u8 * format_signal (u8 * s, va_list * args)
860 {
861   uword signum = va_arg (*args, uword);
862   char * t = 0;
863   switch (signum)
864     {
865 #define _(x) case x: t = #x; break;
866       _ (SIGHUP);
867       _ (SIGINT);
868       _ (SIGQUIT);
869       _ (SIGILL);
870       _ (SIGTRAP);
871       _ (SIGABRT);
872       _ (SIGBUS);
873       _ (SIGFPE);
874       _ (SIGKILL);
875       _ (SIGUSR1);
876       _ (SIGSEGV);
877       _ (SIGUSR2);
878       _ (SIGPIPE);
879       _ (SIGALRM);
880       _ (SIGTERM);
881 #ifdef SIGSTKFLT
882       _ (SIGSTKFLT);
883 #endif
884       _ (SIGCHLD);
885       _ (SIGCONT);
886       _ (SIGSTOP);
887       _ (SIGTSTP);
888       _ (SIGTTIN);
889       _ (SIGTTOU);
890       _ (SIGURG);
891       _ (SIGXCPU);
892       _ (SIGXFSZ);
893       _ (SIGVTALRM);
894       _ (SIGPROF);
895       _ (SIGWINCH);
896       _ (SIGIO);
897       _ (SIGPWR);
898 #ifdef SIGSYS
899       _ (SIGSYS);
900 #endif
901 #undef _
902     default:
903       return format (s, "unknown %d", signum);
904     }
905
906   vec_add (s, t, strlen (t));
907   return s;
908 }
909
910 u8 * format_ucontext_pc (u8 * s, va_list * args)
911 {
912   ucontext_t * uc __attribute__((unused));
913   unsigned long * regs = 0;
914   uword reg_no = 0;
915
916   uc = va_arg (*args, ucontext_t *);
917
918 #if defined (powerpc)
919   regs = &uc->uc_mcontext.uc_regs->gregs[0];
920 #elif defined (powerpc64)
921   regs = &uc->uc_mcontext.uc_regs->gp_regs[0];
922 #elif defined (i386) || defined (__x86_64__)
923   regs = (void *) &uc->uc_mcontext.gregs[0];
924 #endif
925
926 #if defined (powerpc) || defined (powerpc64)
927   reg_no = PT_NIP;
928 #elif defined (i386)
929   reg_no = REG_EIP;
930 #elif defined (__x86_64__)
931   reg_no = REG_RIP;
932 #else
933   reg_no = 0;
934   regs = 0;
935 #endif
936
937   if (! regs)
938     return format (s, "unsupported");
939   else
940     return format (s, "%p", regs[reg_no]);
941 }
942
943 __clib_export uword
944 unformat_unix_gid (unformat_input_t * input, va_list * args)
945 {
946   gid_t *gid = va_arg (*args, gid_t *);
947   struct group *grp = 0;
948   int r;
949   u8 *s;
950
951   if (unformat (input, "%d", &r))
952     {
953       grp = getgrgid (r);
954     }
955   else if (unformat (input, "%s", &s))
956     {
957       grp = getgrnam ((char *) s);
958       vec_free (s);
959     }
960   if (grp)
961     {
962       *gid = grp->gr_gid;
963       return 1;
964     }
965   return 0;
966 }
967
968 #endif /* __KERNEL__ */