af4eed4a42d89fd83077836f1d5058b7bbdd9fae
[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    0x10
41
42 int ipcalc_main(int argc, char **argv)
43 {
44         unsigned long mode;
45
46         unsigned long netmask = 0;
47         unsigned long broadcast;
48         unsigned long network;
49         unsigned long ipaddr;
50
51         static const struct option long_options[] = {
52                 {"netmask", no_argument, NULL, 'n'},
53                 {"broadcast", no_argument, NULL, 'b'},
54                 {"network", no_argument, NULL, 'w'},
55 #ifdef CONFIG_FEATURE_IPCALC_FANCY
56                 {"hostname", no_argument, NULL, 'h'},
57                 {"silent", no_argument, NULL, 's'},
58 #endif
59                 {NULL, 0, NULL, 0}
60         };
61
62         bb_applet_long_options = long_options;
63         mode = bb_getopt_ulflags(argc, argv,
64 #ifdef CONFIG_FEATURE_IPCALC_FANCY
65                                                           "nbwhs");
66 #else
67                                                           "nbw");
68 #endif
69         if (mode & (BROADCAST | NETWORK)) {
70                 if (argc - optind > 2) {
71                         bb_show_usage();
72                 }
73         } else {
74                 if (argc - optind != 1) {
75                         bb_show_usage();
76                 }
77         }
78
79         ipaddr = inet_addr(argv[optind]);
80
81         if (ipaddr == INADDR_NONE) {
82                 IPCALC_MSG(bb_error_msg_and_die("bad IP address: %s", argv[optind]),
83                                    exit(EXIT_FAILURE));
84         }
85
86
87         if (argc - optind == 2) {
88                 netmask = inet_addr(argv[optind + 1]);
89         }
90
91         if (ipaddr == INADDR_NONE) {
92                 IPCALC_MSG(bb_error_msg_and_die("bad netmask: %s", argv[optind + 1]),
93                                    exit(EXIT_FAILURE));
94         }
95
96         /* JHC - If the netmask wasn't provided then calculate it */
97         if (!netmask) {
98                 netmask = get_netmask(ipaddr);
99         }
100
101         if (mode & NETMASK) {
102                 printf("NETMASK=%s\n", inet_ntoa((*(struct in_addr *) &netmask)));
103         }
104
105         if (mode & BROADCAST) {
106                 broadcast = (ipaddr & netmask) | ~netmask;
107                 printf("BROADCAST=%s\n", inet_ntoa((*(struct in_addr *) &broadcast)));
108         }
109
110         if (mode & NETWORK) {
111                 network = ipaddr & netmask;
112                 printf("NETWORK=%s\n", inet_ntoa((*(struct in_addr *) &network)));
113         }
114 #ifdef CONFIG_FEATURE_IPCALC_FANCY
115         if (mode & HOSTNAME) {
116                 struct hostent *hostinfo;
117                 int x;
118
119                 hostinfo = gethostbyaddr((char *) &ipaddr, sizeof(ipaddr), AF_INET);
120                 if (!hostinfo) {
121                         IPCALC_MSG(bb_herror_msg_and_die(
122                                 "cannot find hostname for %s", argv[optind]),);
123                         exit(EXIT_FAILURE);
124                 }
125                 for (x = 0; hostinfo->h_name[x]; x++) {
126                         hostinfo->h_name[x] = tolower(hostinfo->h_name[x]);
127                 }
128
129                 printf("HOSTNAME=%s\n", hostinfo->h_name);
130         }
131 #endif
132
133         return EXIT_SUCCESS;
134 }
135
136 /* END CODE */
137 /*
138 Local Variables:
139 c-file-style: "linux"
140 c-basic-offset: 4
141 tab-width: 4
142 End:
143 */