1 /* $NetBSD: ifconf.c,v 1.1 2014/12/08 04:23:03 ozaki-r Exp $ */ 2 /* 3 * Copyright (c) 2014 The NetBSD Foundation, Inc. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __RCSID("$NetBSD: ifconf.c,v 1.1 2014/12/08 04:23:03 ozaki-r Exp $"); 29 #include <sys/types.h> 30 #include <sys/socket.h> 31 #include <sys/sockio.h> 32 #include <sys/ioctl.h> 33 34 #include <net/if.h> 35 36 #include <stdio.h> 37 #include <err.h> 38 #include <stdlib.h> 39 #include <unistd.h> 40 #include <string.h> 41 42 static void 43 help(void) 44 { 45 fprintf(stderr, "usage:\n\t%s total\n\t%s list [<nifreqs>]\n", 46 getprogname(), getprogname()); 47 exit(EXIT_FAILURE); 48 } 49 50 static int 51 get_number_of_entries(void) 52 { 53 int fd, r; 54 struct ifconf ifc; 55 56 fd = socket(AF_INET, SOCK_DGRAM, 0); 57 if (fd == -1) 58 err(EXIT_FAILURE, "socket"); 59 60 ifc.ifc_len = 0; 61 ifc.ifc_buf = NULL; 62 63 r = ioctl(fd, SIOCGIFCONF, &ifc); 64 if (r == -1) 65 err(EXIT_FAILURE, "ioctl"); 66 67 close(fd); 68 69 return ifc.ifc_len / sizeof(struct ifreq); 70 } 71 72 static void 73 show_number_of_entries(void) 74 { 75 printf("%d\n", get_number_of_entries()); 76 } 77 78 static void 79 show_interfaces(int nifreqs) 80 { 81 int i, fd, r; 82 struct ifconf ifc; 83 struct ifreq *ifreqs; 84 85 if (nifreqs == 0) 86 nifreqs = get_number_of_entries(); 87 88 if (nifreqs <= 0) 89 errx(EXIT_FAILURE, "nifreqs=%d", nifreqs); 90 91 ifreqs = malloc(sizeof(struct ifreq) * nifreqs); 92 if (ifreqs == NULL) 93 err(EXIT_FAILURE, "malloc(sizeof(ifreq) * %d)", nifreqs); 94 95 fd = socket(AF_INET, SOCK_DGRAM, 0); 96 if (fd == -1) 97 err(EXIT_FAILURE, "socket"); 98 99 ifc.ifc_len = sizeof(struct ifreq) * nifreqs; 100 ifc.ifc_req = ifreqs; 101 102 r = ioctl(fd, SIOCGIFCONF, &ifc); 103 if (r == -1) 104 err(EXIT_FAILURE, "ioctl"); 105 close(fd); 106 107 for (i=0; i < (int)(ifc.ifc_len / sizeof(struct ifreq)); i++) { 108 printf("%s: af=%hhu socklen=%hhu\n", ifreqs[i].ifr_name, 109 ifreqs[i].ifr_addr.sa_family, ifreqs[i].ifr_addr.sa_len); 110 } 111 112 free(ifreqs); 113 } 114 115 int 116 main(int argc, char *argv[]) 117 { 118 if (argc < 2) 119 help(); 120 121 if (strcmp(argv[1], "total") == 0) { 122 show_number_of_entries(); 123 } else if (strcmp(argv[1], "list") == 0) { 124 if (argc == 2) 125 show_interfaces(0); 126 else if (argc == 3) 127 show_interfaces(atoi(argv[2])); 128 else 129 help(); 130 } else 131 help(); 132 133 return EXIT_SUCCESS; 134 } 135