Line data Source code
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 : #ifdef AF_NETLINK
67 : #include <linux/types.h>
68 : #include <linux/netlink.h>
69 : #endif
70 : #endif
71 :
72 : #endif /* ! __KERNEL__ */
73 :
74 :
75 : #ifdef __KERNEL__
76 : # include <linux/socket.h>
77 : # include <linux/in.h>
78 : # include <linux/ip.h>
79 : # include <linux/tcp.h>
80 : # include <linux/udp.h>
81 : # include <linux/icmp.h>
82 : # include <linux/if_ether.h>
83 : # include <linux/if_arp.h>
84 : #else
85 : # include <net/if.h> /* struct ifnet may live here */
86 : # include <netinet/in.h>
87 : # include <netinet/ip.h>
88 : # include <netinet/tcp.h>
89 : # include <netinet/udp.h>
90 : # include <netinet/ip_icmp.h>
91 : # include <netinet/if_ether.h>
92 : #endif /* __KERNEL__ */
93 :
94 : #include <vppinfra/format.h>
95 : #include <vppinfra/error.h>
96 :
97 : /* Format unix network address family (e.g. AF_INET). */
98 0 : u8 * format_address_family (u8 * s, va_list * va)
99 : {
100 0 : uword family = va_arg (*va, uword);
101 0 : u8 * t = (u8 *) "UNKNOWN";
102 0 : switch (family)
103 : {
104 : #define _(x) case PF_##x: t = (u8 *) #x; break
105 0 : _ (UNSPEC);
106 0 : _ (UNIX); /* Unix domain sockets */
107 0 : _ (INET); /* Internet IP Protocol */
108 : #ifdef PF_AX25
109 0 : _ (AX25); /* Amateur Radio AX.25 */
110 : #endif
111 : #ifdef PF_IPX
112 0 : _ (IPX); /* Novell IPX */
113 : #endif
114 : #ifdef PF_APPLETALK
115 0 : _ (APPLETALK); /* AppleTalk DDP */
116 : #endif
117 : #ifdef PF_NETROM
118 0 : _ (NETROM); /* Amateur Radio NET/ROM */
119 : #endif
120 : #ifdef PF_BRIDGE
121 0 : _ (BRIDGE); /* Multiprotocol bridge */
122 : #endif
123 : #ifdef PF_ATMPVC
124 0 : _ (ATMPVC); /* ATM PVCs */
125 : #endif
126 : #ifdef PF_X25
127 0 : _ (X25); /* Reserved for X.25 project */
128 : #endif
129 : #ifdef PF_INET6
130 0 : _ (INET6); /* IP version 6 */
131 : #endif
132 : #ifdef PF_ROSE
133 0 : _ (ROSE); /* Amateur Radio X.25 PLP */
134 : #endif
135 : #ifdef PF_DECnet
136 0 : _ (DECnet); /* Reserved for DECnet project */
137 : #endif
138 : #ifdef PF_NETBEUI
139 0 : _ (NETBEUI); /* Reserved for 802.2LLC project*/
140 : #endif
141 : #ifdef PF_SECURITY
142 0 : _ (SECURITY); /* Security callback pseudo AF */
143 : #endif
144 : #ifdef PF_KEY
145 0 : _ (KEY); /* PF_KEY key management API */
146 : #endif
147 : #ifdef PF_NETLINK
148 0 : _ (NETLINK);
149 : #endif
150 : #ifdef PF_PACKET
151 0 : _ (PACKET); /* Packet family */
152 : #endif
153 : #ifdef PF_ASH
154 0 : _ (ASH); /* Ash */
155 : #endif
156 : #ifdef PF_ECONET
157 0 : _ (ECONET); /* Acorn Econet */
158 : #endif
159 : #ifdef PF_ATMSVC
160 0 : _ (ATMSVC); /* ATM SVCs */
161 : #endif
162 : #ifdef PF_SNA
163 0 : _ (SNA); /* Linux SNA Project */
164 : #endif
165 : #ifdef PF_IRDA
166 0 : _ (IRDA); /* IRDA sockets */
167 : #endif
168 : #undef _
169 : }
170 0 : vec_add (s, t, strlen ((char *) t));
171 0 : return s;
172 : }
173 :
174 0 : u8 * format_network_protocol (u8 * s, va_list * args)
175 : {
176 0 : uword family = va_arg (*args, uword);
177 0 : uword protocol = va_arg (*args, uword);
178 :
179 : #ifndef __KERNEL__
180 0 : struct protoent * p = getprotobynumber (protocol);
181 :
182 0 : ASSERT (family == AF_INET);
183 0 : if (p)
184 0 : return format (s, "%s", p->p_name);
185 : else
186 0 : return format (s, "%d", protocol);
187 : #else
188 : return format (s, "%d/%d", family, protocol);
189 : #endif
190 : }
191 :
192 0 : u8 * format_network_port (u8 * s, va_list * args)
193 : {
194 0 : uword proto = va_arg (*args, uword);
195 0 : uword port = va_arg (*args, uword);
196 :
197 : #ifndef __KERNEL__
198 0 : struct servent * p = getservbyport (port, proto == IPPROTO_UDP ? "udp" : "tcp");
199 :
200 0 : if (p)
201 0 : return format (s, "%s", p->s_name);
202 : else
203 0 : return format (s, "%d", port);
204 : #else
205 : return format (s, "%s/%d", proto == IPPROTO_UDP ? "udp" : "tcp", port);
206 : #endif
207 : }
208 :
209 : /* Format generic network address: takes two arguments family and address.
210 : Assumes network byte order. */
211 0 : u8 * format_network_address (u8 * s, va_list * args)
212 : {
213 0 : uword family = va_arg (*args, uword);
214 0 : u8 * addr = va_arg (*args, u8 *);
215 :
216 0 : switch (family)
217 : {
218 0 : case AF_INET:
219 0 : s = format (s, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
220 0 : break;
221 :
222 0 : case AF_UNSPEC:
223 : /* We use AF_UNSPEC for ethernet addresses. */
224 0 : s = format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
225 0 : addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
226 0 : break;
227 :
228 0 : default:
229 0 : clib_error ("unsupported address family %d", family);
230 : }
231 :
232 0 : return s;
233 : }
234 :
235 0 : u8 * format_sockaddr (u8 * s, va_list * args)
236 : {
237 0 : void * v = va_arg (*args, void *);
238 0 : struct sockaddr * sa = v;
239 : static u32 local_counter;
240 :
241 0 : switch (sa->sa_family)
242 : {
243 0 : case AF_INET:
244 : {
245 0 : struct sockaddr_in * i = v;
246 0 : s = format (s, "%U:%U",
247 : format_network_address, AF_INET, &i->sin_addr.s_addr,
248 0 : format_network_port, IPPROTO_TCP, ntohs (i->sin_port));
249 : }
250 0 : break;
251 :
252 0 : case AF_LOCAL:
253 : {
254 : /*
255 : * There isn't anything useful to print.
256 : * The unix cli world uses the output to make a node name,
257 : * so we need to return a unique name.
258 : */
259 0 : s = format (s, "local:%u", local_counter++);
260 : }
261 0 : break;
262 :
263 : #ifndef __KERNEL__
264 : #ifdef AF_NETLINK
265 0 : case AF_NETLINK:
266 : {
267 0 : struct sockaddr_nl * n = v;
268 0 : s = format (s, "KERNEL-NETLINK");
269 0 : if (n->nl_groups)
270 0 : s = format (s, " (groups 0x%x)", n->nl_groups);
271 0 : break;
272 : }
273 : #endif
274 : #endif
275 :
276 0 : default:
277 0 : s = format (s, "sockaddr family %d", sa->sa_family);
278 0 : break;
279 : }
280 :
281 0 : return s;
282 : }
283 :
284 : #ifndef __APPLE__
285 :
286 : #ifndef __KERNEL__
287 276155 : u8 * format_timeval (u8 * s, va_list * args)
288 : {
289 276155 : char * fmt = va_arg (*args, char *);
290 276155 : struct timeval * tv = va_arg (*args, struct timeval *);
291 : struct tm * tm;
292 : word msec;
293 : char * f, c;
294 :
295 276155 : if (! fmt)
296 276155 : fmt = "y/m/d H:M:S:F";
297 :
298 276155 : if (! tv)
299 : {
300 : static struct timeval now;
301 0 : gettimeofday (&now, 0);
302 0 : tv = &now;
303 : }
304 :
305 276155 : msec = flt_round_nearest (1e-3 * tv->tv_usec);
306 276155 : if (msec >= 1000)
307 66 : { msec = 0; tv->tv_sec++; }
308 :
309 : {
310 276155 : time_t t = tv->tv_sec;
311 276155 : tm = localtime (&t);
312 : }
313 :
314 3866170 : for (f = fmt; *f; f++)
315 : {
316 : uword what;
317 3590020 : char * what_fmt = "%d";
318 :
319 3590020 : switch (c = *f)
320 : {
321 1656930 : default:
322 1656930 : vec_add1 (s, c);
323 1656930 : continue;
324 :
325 276155 : case 'y':
326 276155 : what = 1900 + tm->tm_year;
327 276155 : what_fmt = "%4d";
328 276155 : break;
329 276155 : case 'm':
330 276155 : what = tm->tm_mon + 1;
331 276155 : what_fmt = "%02d";
332 276155 : break;
333 276155 : case 'd':
334 276155 : what = tm->tm_mday;
335 276155 : what_fmt = "%02d";
336 276155 : break;
337 276155 : case 'H':
338 276155 : what = tm->tm_hour;
339 276155 : what_fmt = "%02d";
340 276155 : break;
341 276155 : case 'M':
342 276155 : what = tm->tm_min;
343 276155 : what_fmt = "%02d";
344 276155 : break;
345 276155 : case 'S':
346 276155 : what = tm->tm_sec;
347 276155 : what_fmt = "%02d";
348 276155 : break;
349 276155 : case 'F':
350 276155 : what = msec;
351 276155 : what_fmt = "%03d";
352 276155 : break;
353 : }
354 :
355 1933080 : s = format (s, what_fmt, what);
356 : }
357 :
358 276155 : return s;
359 : }
360 : #endif
361 :
362 276155 : u8 * format_time_float (u8 * s, va_list * args)
363 : {
364 276155 : u8 * fmt = va_arg (*args, u8 *);
365 276155 : f64 t = va_arg (*args, f64);
366 : struct timeval tv;
367 276155 : if (t <= 0)
368 0 : t = unix_time_now ();
369 276155 : tv.tv_sec = t;
370 276155 : tv.tv_usec = 1e6*(t - tv.tv_sec);
371 276155 : return format (s, "%U", format_timeval, fmt, &tv);
372 : }
373 :
374 575 : u8 * format_signal (u8 * s, va_list * args)
375 : {
376 575 : uword signum = va_arg (*args, uword);
377 575 : char * t = 0;
378 575 : switch (signum)
379 : {
380 : #define _(x) case x: t = #x; break;
381 0 : _ (SIGHUP);
382 0 : _ (SIGINT);
383 0 : _ (SIGQUIT);
384 0 : _ (SIGILL);
385 0 : _ (SIGTRAP);
386 0 : _ (SIGABRT);
387 0 : _ (SIGBUS);
388 0 : _ (SIGFPE);
389 0 : _ (SIGKILL);
390 0 : _ (SIGUSR1);
391 0 : _ (SIGSEGV);
392 0 : _ (SIGUSR2);
393 0 : _ (SIGPIPE);
394 0 : _ (SIGALRM);
395 575 : _ (SIGTERM);
396 : #ifdef SIGSTKFLT
397 0 : _ (SIGSTKFLT);
398 : #endif
399 0 : _ (SIGCHLD);
400 0 : _ (SIGCONT);
401 0 : _ (SIGSTOP);
402 0 : _ (SIGTSTP);
403 0 : _ (SIGTTIN);
404 0 : _ (SIGTTOU);
405 0 : _ (SIGURG);
406 0 : _ (SIGXCPU);
407 0 : _ (SIGXFSZ);
408 0 : _ (SIGVTALRM);
409 0 : _ (SIGPROF);
410 0 : _ (SIGWINCH);
411 0 : _ (SIGIO);
412 0 : _ (SIGPWR);
413 : #ifdef SIGSYS
414 0 : _ (SIGSYS);
415 : #endif
416 : #undef _
417 0 : default:
418 0 : return format (s, "unknown %d", signum);
419 : }
420 :
421 575 : vec_add (s, t, strlen (t));
422 575 : return s;
423 : }
424 :
425 575 : u8 * format_ucontext_pc (u8 * s, va_list * args)
426 : {
427 : ucontext_t * uc __attribute__((unused));
428 575 : unsigned long * regs = 0;
429 575 : uword reg_no = 0;
430 :
431 575 : uc = va_arg (*args, ucontext_t *);
432 :
433 : #if defined (powerpc)
434 : regs = &uc->uc_mcontext.uc_regs->gregs[0];
435 : #elif defined (powerpc64)
436 : regs = &uc->uc_mcontext.uc_regs->gp_regs[0];
437 : #elif defined (i386) || defined (__x86_64__)
438 575 : regs = (void *) &uc->uc_mcontext.gregs[0];
439 : #elif defined(__aarch64__)
440 : regs = (void *) &uc->uc_mcontext.pc;
441 : #endif
442 :
443 : #if defined (powerpc) || defined (powerpc64)
444 : reg_no = PT_NIP;
445 : #elif defined (i386)
446 : reg_no = REG_EIP;
447 : #elif defined (__x86_64__)
448 575 : reg_no = REG_RIP;
449 : #elif defined(__aarch64__)
450 : reg_no = 0;
451 : #else
452 : reg_no = 0;
453 : regs = 0;
454 : #endif
455 :
456 575 : if (! regs)
457 0 : return format (s, "unsupported");
458 : else
459 575 : return format (s, "%p", regs[reg_no]);
460 : }
461 :
462 : __clib_export uword
463 0 : unformat_unix_gid (unformat_input_t * input, va_list * args)
464 : {
465 0 : gid_t *gid = va_arg (*args, gid_t *);
466 0 : struct group *grp = 0;
467 : int r;
468 : u8 *s;
469 :
470 0 : if (unformat (input, "%d", &r))
471 : {
472 0 : grp = getgrgid (r);
473 : }
474 0 : else if (unformat (input, "%s", &s))
475 : {
476 0 : grp = getgrnam ((char *) s);
477 0 : vec_free (s);
478 : }
479 0 : if (grp)
480 : {
481 0 : *gid = grp->gr_gid;
482 0 : return 1;
483 : }
484 0 : return 0;
485 : }
486 :
487 : #endif /* __KERNEL__ */
|