2c23d17f6df700ed9ef88799ffffbb45711b9758
[oweals/busybox.git] / networking / ipcalc.c
1 /* vi: set sw=4 ts=4 ai: */
2 /*
3  * Mini ipcalc implementation for busybox
4  *
5  * By Jordan Crouse <jordan@cosmicpenguin.net>
6  *    Stephan Linz  <linz@li-pro.net>
7  *
8  * This is a complete reimplentation of the ipcalc program
9  * from Redhat.  I didn't look at their source code, but there
10  * is no denying that this is a loving reimplementation
11  */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <ctype.h>
16 #include <getopt.h>
17 #include <sys/socket.h>
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
20
21 #include "busybox.h"
22
23 #define IPCALC_MSG(CMD,ALTCMD) if (mode & SILENT) {ALTCMD;} else {CMD;}
24
25 static unsigned long get_netmask(unsigned long ipaddr)
26 {
27         if (ipaddr & 0xC0) {
28                 return 0x00FFFFFF;      /* Class C */
29         }
30         if (ipaddr & 0x10) {
31                 return 0x0000FFFF;      /* Class B */
32         }
33         return 0x000000FF;      /* Class A */
34 }
35
36 #define NETMASK   0x01
37 #define BROADCAST 0x02
38 #define NETWORK   0x04
39 #define HOSTNAME  0x08
40 #define SILENT    0x80
41
42 int ipcalc_main(int argc, char **argv)
43 {
44         unsigned char mode = 0;
45
46         unsigned long netmask = 0;
47         unsigned long broadcast = 0;
48         unsigned long network = 0;
49         unsigned long ipaddr = 0;
50
51         int opt = 0;
52
53         struct option long_options[] = {
54                 {"netmask", no_argument, NULL, 'n'},
55                 {"broadcast", no_argument, NULL, 'b'},
56                 {"network", no_argument, NULL, 'w'},
57 #ifdef CONFIG_FEATURE_IPCALC_FANCY
58                 {"hostname", no_argument, NULL, 'h'},
59                 {"silent", no_argument, NULL, 's'},
60 #endif
61                 {NULL, 0, NULL, 0}
62         };
63
64
65         while ((opt = getopt_long(argc, argv,
66 #ifdef CONFIG_FEATURE_IPCALC_FANCY
67                                                           "nbwhs",
68 #else
69                                                           "nbw",
70 #endif
71                                                           long_options, NULL)) != EOF) {
72                 if (opt == 'n')
73                         mode |= NETMASK;
74                 else if (opt == 'b')
75                         mode |= BROADCAST;
76                 else if (opt == 'w')
77                         mode |= NETWORK;
78 #ifdef CONFIG_FEATURE_IPCALC_FANCY
79                 else if (opt == 'h')
80                         mode |= HOSTNAME;
81                 else if (opt == 's')
82                         mode |= SILENT;
83 #endif
84                 else {
85                         bb_show_usage();
86                 }
87         }
88
89         if (mode & (BROADCAST | NETWORK)) {
90                 if (argc - optind > 2) {
91                         bb_show_usage();
92                 }
93         } else {
94                 if (argc - optind != 1) {
95                         bb_show_usage();
96                 }
97         }
98
99         ipaddr = inet_addr(argv[optind]);
100
101         if (ipaddr == INADDR_NONE) {
102                 IPCALC_MSG(bb_error_msg_and_die("bad IP address: %s\n", argv[optind]),
103                                    exit(EXIT_FAILURE));
104         }
105
106
107         if (argc - optind == 2) {
108                 netmask = inet_addr(argv[optind + 1]);
109         }
110
111         if (ipaddr == INADDR_NONE) {
112                 IPCALC_MSG(bb_error_msg_and_die("bad netmask: %s\n", argv[optind + 1]),
113                                    exit(EXIT_FAILURE));
114         }
115
116         /* JHC - If the netmask wasn't provided then calculate it */
117         if (!netmask) {
118                 netmask = get_netmask(ipaddr);
119         }
120
121         if (mode & NETMASK) {
122                 printf("NETMASK=%s\n", inet_ntoa((*(struct in_addr *) &netmask)));
123         }
124
125         if (mode & BROADCAST) {
126                 broadcast = (ipaddr & netmask) | ~netmask;
127                 printf("BROADCAST=%s\n", inet_ntoa((*(struct in_addr *) &broadcast)));
128         }
129
130         if (mode & NETWORK) {
131                 network = ipaddr & netmask;
132                 printf("NETWORK=%s\n", inet_ntoa((*(struct in_addr *) &network)));
133         }
134 #ifdef CONFIG_FEATURE_IPCALC_FANCY
135         if (mode & HOSTNAME) {
136                 struct hostent *hostinfo;
137                 int x;
138
139                 hostinfo = gethostbyaddr((char *) &ipaddr, sizeof(ipaddr), AF_INET);
140                 if (!hostinfo) {
141                         IPCALC_MSG(bb_error_msg("cannot find hostname for %s", argv[optind]);
142                                            herror(NULL);
143                                            putc('\n', stderr);,);
144                         exit(EXIT_FAILURE);
145                 }
146                 for (x = 0; hostinfo->h_name[x]; x++) {
147                         hostinfo->h_name[x] = tolower(hostinfo->h_name[x]);
148                 }
149
150                 printf("HOSTNAME=%s\n", hostinfo->h_name);
151         }
152 #endif
153
154         return EXIT_SUCCESS;
155 }
156
157 /* END CODE */
158 /*
159 Local Variables:
160 c-file-style: "linux"
161 c-basic-offset: 4
162 tab-width: 4
163 End:
164 */