This commit was generated by cvs2svn to compensate for changes in r120,
[util-vserver.git] / src / ifspec.c
1 // $Id: ifspec.c,v 1.1.4.1 2003/11/21 16:01:09 ensc Exp $
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 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <ctype.h>
31 #include <unistd.h>
32 #include <sys/socket.h>
33 #include <sys/ioctl.h>
34 #include <netinet/in.h>
35 #include <net/if.h>
36
37 static void usage()
38 {
39         fprintf (stderr,"ifspec version %s\n",VERSION);
40         fprintf (stderr
41                 ,"ifspec network-device [ ipaddr netmask broadcast ]\n"
42                  "prints device specification in a shell usable way\n");
43         exit (-1);
44 }
45
46 static int ifconfig_ioctl(
47         int fd,
48         const char *ifname,
49         int cmd,
50         struct ifreq *ifr)
51 {
52         strcpy(ifr->ifr_name, ifname);
53         return ioctl(fd, cmd,ifr);
54 }
55
56 static unsigned long ip_cnv (const char *str)
57 {
58         const char *start_str = str;
59         unsigned tb[4];
60         int no = 0;
61         unsigned long ret;
62           
63         memset (tb,-1,sizeof(tb));
64         while (*str != '\0' && no < 4){
65                 if (isdigit(*str)){
66                         int val = atoi(str);
67                         if (val > 255) break;
68                         tb[no++] = val;
69                         while (isdigit(*str)) str++;
70                         if (*str == '.'){
71                                 str++;
72                         }else{
73                                 break;
74                         }
75                 }else{
76                         break;
77                 }
78         }
79
80         ret = (tb[0] << 24) | (tb[1]<<16) | (tb[2] << 8) | tb[3];
81         if (no != 4 || *str != '\0'){
82                 fprintf (stderr,"Invalid IP number or netmask: %s\n",start_str);
83                 ret = 0xffffffff;
84         }
85         return ret;
86 }
87
88
89 /*
90         Fetch the IP number of an interface from the kernel.
91         Assume the device is already available in the kernel
92         Return -1 if any error.
93 */
94 int ifconfig_print (
95         const char *ifname,
96         const char *addrstr,
97         const char *maskstr,
98         const char *bcaststr)
99 {
100         int ret = -1;
101         int skfd = socket(AF_INET, SOCK_DGRAM, 0);
102         if (skfd != -1){
103                 struct ifreq ifr;
104                 struct {
105                         unsigned long addr;
106                         unsigned long mask;
107                 } solved = {0,0};
108                 if (addrstr != NULL && addrstr[0] != '\0'){
109                         printf ("ADDR=%s\n",addrstr);
110                         solved.addr = ip_cnv (addrstr);
111                 }else if (ifconfig_ioctl(skfd,ifname,SIOCGIFADDR, &ifr) >= 0){
112                         struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr;
113                         unsigned long addr = ntohl(sin->sin_addr.s_addr);
114                         printf ("ADDR=%lu.%lu.%lu.%lu\n"
115                                 ,(addr>>24)&0xff
116                                 ,(addr>>16)&0xff
117                                 ,(addr>>8)&0xff
118                                 ,addr&0xff);
119                         solved.addr = addr;
120                         ret = 0;
121                 }
122                 else {
123                   perror("ioctl(SIOCGIFADDR)");
124                 }
125                 
126                 if (maskstr != NULL && maskstr[0] != '\0'){
127                         printf ("NETMASK=%s\n",maskstr);
128                         solved.mask = ip_cnv (maskstr);
129                 }else           if (ifconfig_ioctl(skfd,ifname,SIOCGIFNETMASK, &ifr) >= 0){
130                         struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr;
131                         unsigned long addr = ntohl(sin->sin_addr.s_addr);
132                         printf ("NETMASK=%lu.%lu.%lu.%lu\n"
133                                 ,(addr>>24)&0xff
134                                 ,(addr>>16)&0xff
135                                 ,(addr>>8)&0xff
136                                 ,addr&0xff);
137                         solved.mask = addr;
138                         ret = 0;
139                 }
140                 else {
141                   perror("ioctl(SIOCGIFNETMASK)");
142                 }
143                 
144                 if (bcaststr != NULL && bcaststr[0] != '\0'){
145                         printf ("BCAST=%s\n",bcaststr);
146                 }else if (ifconfig_ioctl(skfd,ifname,SIOCGIFBRDADDR, &ifr) >= 0){
147                         struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr;
148                         unsigned long addr = ntohl(sin->sin_addr.s_addr);
149                         printf ("BCAST=%lu.%lu.%lu.%lu\n"
150                                 ,(addr>>24)&0xff
151                                 ,(addr>>16)&0xff
152                                 ,(addr>>8)&0xff
153                                 ,addr&0xff);
154                         ret = 0;
155                 }else if (solved.addr!=0 && solved.mask!=0) {
156                         // Can't get it from the kernel, compute it from the IP
157                         // and the netmask
158                         unsigned long addr = (solved.addr & solved.mask)
159                                 | ~solved.mask;
160                         printf ("BCAST=%lu.%lu.%lu.%lu\n"
161                                 ,(addr>>24)&0xff
162                                 ,(addr>>16)&0xff
163                                 ,(addr>>8)&0xff
164                                 ,addr&0xff);
165                         
166                 }
167                 close (skfd);
168         }
169         return ret;
170 }
171
172
173 int main (int argc, char *argv[])
174 {
175         int ret = -1;
176         if (argc < 2){
177                 usage();
178         }else{
179                 const char *addrstr = argc >= 3 ? argv[2] : NULL;
180                 const char *maskstr = argc >= 4 ? argv[3] : NULL;
181                 const char *bcaststr = argc >= 5 ? argv[4] : NULL;
182                 ret = ifconfig_print (argv[1],addrstr,maskstr,bcaststr);
183         }
184         return ret;
185 }
186
187
188