ifspec.c (4672B)
1 // $Id$ 2 3 // Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de> 4 // based on ifspec.cc by Jacques Gelinas 5 // 6 // This program is free software; you can redistribute it and/or modify 7 // it under the terms of the GNU General Public License as published by 8 // the Free Software Foundation; either version 2, or (at your option) 9 // any later version. 10 // 11 // This program is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 // 16 // You should have received a copy of the GNU General Public License 17 // along with this program; if not, write to the Free Software 18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 20 /* 21 Prints the specs of a network device in shell like form 22 23 ADDR= 24 NETMASK= 25 BCAST= 26 */ 27 #ifdef HAVE_CONFIG_H 28 # include <config.h> 29 #endif 30 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <string.h> 34 #include <ctype.h> 35 #include <unistd.h> 36 #include <sys/socket.h> 37 #include <sys/ioctl.h> 38 #include <netinet/in.h> 39 #include <net/if.h> 40 41 static void usage() 42 { 43 fprintf (stderr,"ifspec version %s\n",VERSION); 44 fprintf (stderr 45 ,"ifspec network-device [ ipaddr netmask broadcast ]\n" 46 "prints device specification in a shell usable way\n"); 47 exit (-1); 48 } 49 50 static int ifconfig_ioctl( 51 int fd, 52 const char *ifname, 53 int cmd, 54 struct ifreq *ifr) 55 { 56 strcpy(ifr->ifr_name, ifname); 57 return ioctl(fd, cmd,ifr); 58 } 59 60 static unsigned long ip_cnv (const char *str) 61 { 62 const char *start_str = str; 63 unsigned tb[4]; 64 int no = 0; 65 unsigned long ret; 66 67 memset (tb,-1,sizeof(tb)); 68 while (*str != '\0' && no < 4){ 69 if (isdigit(*str)){ 70 int val = atoi(str); 71 if (val > 255) break; 72 tb[no++] = val; 73 while (isdigit(*str)) str++; 74 if (*str == '.'){ 75 str++; 76 }else{ 77 break; 78 } 79 }else{ 80 break; 81 } 82 } 83 84 ret = (tb[0] << 24) | (tb[1]<<16) | (tb[2] << 8) | tb[3]; 85 if (no != 4 || *str != '\0'){ 86 fprintf (stderr,"Invalid IP number or netmask: %s\n",start_str); 87 ret = 0xffffffff; 88 } 89 return ret; 90 } 91 92 93 /* 94 Fetch the IP number of an interface from the kernel. 95 Assume the device is already available in the kernel 96 Return -1 if any error. 97 */ 98 int ifconfig_print ( 99 const char *ifname, 100 const char *addrstr, 101 const char *maskstr, 102 const char *bcaststr) 103 { 104 int ret = -1; 105 int skfd = socket(AF_INET, SOCK_DGRAM, 0); 106 if (skfd != -1){ 107 struct ifreq ifr; 108 struct { 109 unsigned long addr; 110 unsigned long mask; 111 } solved = {0,0}; 112 if (addrstr != NULL && addrstr[0] != '\0'){ 113 printf ("ADDR=%s\n",addrstr); 114 solved.addr = ip_cnv (addrstr); 115 }else if (ifconfig_ioctl(skfd,ifname,SIOCGIFADDR, &ifr) >= 0){ 116 struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr; 117 unsigned long addr = ntohl(sin->sin_addr.s_addr); 118 printf ("ADDR=%lu.%lu.%lu.%lu\n" 119 ,(addr>>24)&0xff 120 ,(addr>>16)&0xff 121 ,(addr>>8)&0xff 122 ,addr&0xff); 123 solved.addr = addr; 124 ret = 0; 125 } 126 else { 127 perror("ifspec: ioctl(SIOCGIFADDR)"); 128 } 129 130 if (maskstr != NULL && maskstr[0] != '\0'){ 131 printf ("NETMASK=%s\n",maskstr); 132 solved.mask = ip_cnv (maskstr); 133 }else if (ifconfig_ioctl(skfd,ifname,SIOCGIFNETMASK, &ifr) >= 0){ 134 struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr; 135 unsigned long addr = ntohl(sin->sin_addr.s_addr); 136 printf ("NETMASK=%lu.%lu.%lu.%lu\n" 137 ,(addr>>24)&0xff 138 ,(addr>>16)&0xff 139 ,(addr>>8)&0xff 140 ,addr&0xff); 141 solved.mask = addr; 142 ret = 0; 143 } 144 else { 145 perror("ifspec: ioctl(SIOCGIFNETMASK)"); 146 } 147 148 if (bcaststr != NULL && bcaststr[0] != '\0'){ 149 printf ("BCAST=%s\n",bcaststr); 150 }else if (ifconfig_ioctl(skfd,ifname,SIOCGIFBRDADDR, &ifr) >= 0){ 151 struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr; 152 unsigned long addr = ntohl(sin->sin_addr.s_addr); 153 printf ("BCAST=%lu.%lu.%lu.%lu\n" 154 ,(addr>>24)&0xff 155 ,(addr>>16)&0xff 156 ,(addr>>8)&0xff 157 ,addr&0xff); 158 ret = 0; 159 }else if (solved.addr!=0 && solved.mask!=0) { 160 // Can't get it from the kernel, compute it from the IP 161 // and the netmask 162 unsigned long addr = (solved.addr & solved.mask) 163 | ~solved.mask; 164 printf ("BCAST=%lu.%lu.%lu.%lu\n" 165 ,(addr>>24)&0xff 166 ,(addr>>16)&0xff 167 ,(addr>>8)&0xff 168 ,addr&0xff); 169 170 } 171 close (skfd); 172 } 173 return ret; 174 } 175 176 177 int main (int argc, char *argv[]) 178 { 179 int ret = -1; 180 if (argc < 2){ 181 usage(); 182 }else{ 183 const char *addrstr = argc >= 3 ? argv[2] : NULL; 184 const char *maskstr = argc >= 4 ? argv[3] : NULL; 185 const char *bcaststr = argc >= 5 ? argv[4] : NULL; 186 ret = ifconfig_print (argv[1],addrstr,maskstr,bcaststr); 187 } 188 return ret; 189 } 190 191 192