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