|
38 | 38 | #include <sys/types.h> |
39 | 39 | #include <sched.h> |
40 | 40 |
|
| 41 | +#include <linux/netlink.h> |
| 42 | +#include <linux/rtnetlink.h> |
| 43 | +#include <netinet/in.h> |
| 44 | +#include <arpa/inet.h> |
| 45 | +#include <net/if.h> |
| 46 | + |
41 | 47 | #ifdef HAVE_LINUX_IOPRIO_H |
42 | 48 | # include <linux/ioprio.h> |
43 | 49 | #endif |
@@ -374,6 +380,99 @@ memhog (int megabytes) |
374 | 380 | return 0; |
375 | 381 | } |
376 | 382 |
|
| 383 | +#define BUFFER_SIZE 8192 |
| 384 | + |
| 385 | +static void |
| 386 | +dump_net_interface (const char *ifname) |
| 387 | +{ |
| 388 | + struct sockaddr_nl sa; |
| 389 | + struct nlmsghdr *nlh; |
| 390 | + struct ifaddrmsg *ifa; |
| 391 | + char *buffer; |
| 392 | + int ifindex; |
| 393 | + int sock; |
| 394 | + |
| 395 | + ifindex = if_nametoindex (ifname); |
| 396 | + if (ifindex == 0) |
| 397 | + error (EXIT_FAILURE, errno, "if_nametoindex `%s`", ifname); |
| 398 | + |
| 399 | + sock = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); |
| 400 | + if (sock < 0) |
| 401 | + error (EXIT_FAILURE, errno, "socket"); |
| 402 | + |
| 403 | + buffer = malloc (BUFFER_SIZE); |
| 404 | + if (buffer == NULL) |
| 405 | + error (EXIT_FAILURE, errno, "malloc"); |
| 406 | + |
| 407 | + sa.nl_family = AF_NETLINK; |
| 408 | + |
| 409 | + if (bind (sock, (struct sockaddr *) &sa, sizeof (sa)) < 0) |
| 410 | + error (EXIT_FAILURE, errno, "bind"); |
| 411 | + |
| 412 | + nlh = (struct nlmsghdr *) buffer; |
| 413 | + |
| 414 | + memset (buffer, 0, BUFFER_SIZE); |
| 415 | + nlh->nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg)); |
| 416 | + nlh->nlmsg_type = RTM_GETADDR; |
| 417 | + nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; |
| 418 | + nlh->nlmsg_seq = 1; |
| 419 | + |
| 420 | + ifa = NLMSG_DATA (nlh); |
| 421 | + ifa->ifa_family = AF_INET; |
| 422 | + |
| 423 | + if (send (sock, nlh, nlh->nlmsg_len, 0) < 0) |
| 424 | + error (EXIT_FAILURE, errno, "send"); |
| 425 | + |
| 426 | + while (1) |
| 427 | + { |
| 428 | + ssize_t len = recv (sock, buffer, BUFFER_SIZE, 0); |
| 429 | + if (len < 0) |
| 430 | + error (EXIT_FAILURE, errno, "recv"); |
| 431 | + |
| 432 | + for (nlh = (struct nlmsghdr *) buffer; NLMSG_OK (nlh, len); nlh = NLMSG_NEXT (nlh, len)) |
| 433 | + { |
| 434 | + struct rtattr *rta[IFA_MAX + 1] = {}; |
| 435 | + struct rtattr *rta_it; |
| 436 | + int rta_len; |
| 437 | + |
| 438 | + if (nlh->nlmsg_type == NLMSG_DONE) |
| 439 | + goto done; |
| 440 | + if (nlh->nlmsg_type == NLMSG_ERROR) |
| 441 | + error (EXIT_FAILURE, 0, "netlink error"); |
| 442 | + |
| 443 | + ifa = NLMSG_DATA (nlh); |
| 444 | + if (ifa->ifa_index != ifindex) |
| 445 | + continue; |
| 446 | + |
| 447 | + rta_it = IFA_RTA (ifa); |
| 448 | + rta_len = IFA_PAYLOAD (nlh); |
| 449 | + |
| 450 | + while (RTA_OK (rta_it, rta_len)) |
| 451 | + { |
| 452 | + if (rta_it->rta_type <= IFA_MAX) |
| 453 | + rta[rta_it->rta_type] = rta_it; |
| 454 | + rta_it = RTA_NEXT (rta_it, rta_len); |
| 455 | + } |
| 456 | + |
| 457 | + if (rta[IFA_ADDRESS]) |
| 458 | + { |
| 459 | + char addr[INET_ADDRSTRLEN]; |
| 460 | + inet_ntop (AF_INET, RTA_DATA (rta[IFA_LOCAL]), addr, sizeof (addr)); |
| 461 | + printf ("address: %s/%d\n", addr, ifa->ifa_prefixlen); |
| 462 | + } |
| 463 | + if (rta[IFA_BROADCAST]) |
| 464 | + { |
| 465 | + char bcast[INET_ADDRSTRLEN]; |
| 466 | + inet_ntop (AF_INET, RTA_DATA (rta[IFA_BROADCAST]), bcast, sizeof (bcast)); |
| 467 | + printf ("broadcast: %s\n", bcast); |
| 468 | + } |
| 469 | + } |
| 470 | + } |
| 471 | +done: |
| 472 | + close (sock); |
| 473 | + free (buffer); |
| 474 | +} |
| 475 | + |
377 | 476 | int |
378 | 477 | main (int argc, char **argv) |
379 | 478 | { |
@@ -587,6 +686,14 @@ main (int argc, char **argv) |
587 | 686 | return 0; |
588 | 687 | } |
589 | 688 |
|
| 689 | + if (strcmp (argv[1], "ip") == 0) |
| 690 | + { |
| 691 | + if (argc < 2) |
| 692 | + error (EXIT_FAILURE, 0, "'ip' requires an argument"); |
| 693 | + dump_net_interface (argv[2]); |
| 694 | + exit (EXIT_SUCCESS); |
| 695 | + } |
| 696 | + |
590 | 697 | if (strcmp (argv[1], "write") == 0) |
591 | 698 | { |
592 | 699 | if (argc < 3) |
|
0 commit comments