include "compat.h"
[util-vserver.git] / util-vserver / src / ifspec.c
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;
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                 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                 if (bcaststr != NULL && bcaststr[0] != '\0'){
141                         printf ("BCAST=%s\n",bcaststr);
142                 }else if (ifconfig_ioctl(skfd,ifname,SIOCGIFBRDADDR, &ifr) >= 0){
143                         struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr;
144                         unsigned long addr = ntohl(sin->sin_addr.s_addr);
145                         printf ("BCAST=%lu.%lu.%lu.%lu\n"
146                                 ,(addr>>24)&0xff
147                                 ,(addr>>16)&0xff
148                                 ,(addr>>8)&0xff
149                                 ,addr&0xff);
150                         ret = 0;
151                 }else{
152                         // Can't get it from the kernel, compute it from the IP
153                         // and the netmask
154                         unsigned long addr = (solved.addr & solved.mask)
155                                 | ~solved.mask;
156                         printf ("BCAST=%lu.%lu.%lu.%lu\n"
157                                 ,(addr>>24)&0xff
158                                 ,(addr>>16)&0xff
159                                 ,(addr>>8)&0xff
160                                 ,addr&0xff);
161                         
162                 }
163                 close (skfd);
164         }
165         return ret;
166 }
167
168
169 int main (int argc, char *argv[])
170 {
171         int ret = -1;
172         if (argc < 2){
173                 usage();
174         }else{
175                 const char *addrstr = argc >= 3 ? argv[2] : NULL;
176                 const char *maskstr = argc >= 4 ? argv[3] : NULL;
177                 const char *bcaststr = argc >= 5 ? argv[4] : NULL;
178                 ret = ifconfig_print (argv[1],addrstr,maskstr,bcaststr);
179         }
180         return ret;
181 }
182
183
184