1 /*
2     whatnet.c, Copyright (C) 2001-2003 Joe Laffey
3     Network Info Processing for Whatmask
4 
5     $Revision: 1.21 $
6 
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11 
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16 
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 */
21 
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #else
25 #include "myTypes.h"
26 #endif
27 
28 
29 #include <stdlib.h>
30 
31 
32 #ifndef __dest_os
33 #define __dest_os	6969
34 #endif
35 
36 #if __dest_os == __win32_os || __dest_os == __mac_os
37 #define EX_USAGE        64
38 #define EX_DATAERR		65
39 #define EX_SOFTWARE		70
40 #else
41 /* Windoze does not have this - or I can't find it... */
42 #include <sysexits.h>
43 #endif
44 
45 #include <stdio.h>
46 #include <string.h>
47 #include "octets.h"
48 #include "bitfill.h"
49 #include "bitcount.h"
50 #include "validatemask.h"
51 #include "whatnet_printdata.h"
52 #include "myname.h"
53 #include "usage.h"
54 
55 
56 #include "whatnet.h"
57 
whatnet_main(char * myIpPtr,char * myMaskPtr)58 int whatnet_main(char* myIpPtr, char* myMaskPtr)
59 {
60 
61 	uint32 		myIp,		/* ip address */
62 				myMask,		/* subnet mask */
63 				myCIDR,		/* CIDR style mask */
64 				myBr,		/* Broadcast address */
65 				myNt;		/* Network address */
66 
67 	char		myIpStr[NM_LEN],		/* ip address as string */
68 				myMaskStr[NM_LEN],		/* subnet mask as string */
69 				myNtStr[NM_LEN],		/* Network address as string */
70 				myBrStr[NM_LEN],		/* broadcast address as string */
71 				myStartIpStr[NM_LEN],	/* starting usable address as string */
72 				myEndIpStr[NM_LEN],		/* ending usable address as string */
73 				myWildcardStr[NM_LEN],	/* wildcard mask as string */
74 				myCIDRStr[BIT_LEN];		/* CIDR bits as string */
75 
76 	uint32		usableIps; 	/* number of usable ips addresses */
77 
78 
79 
80 	/* try to convert the octets to the ip - this also returns 1 if the conversion fails */
81 	if(octets_to_u_int(&myIp, myIpPtr))
82 	{
83 		fprintf(stderr, "%s: \"%s\" is not a valid IP address! IP addresses take the form\n\"xxx.xxx.xxx.xxx\" where each octet (group of numbers separated by dots) must be\nbetween 0 and 255 inclusive!\n", PACKAGE, myIpPtr);
84 		return(EX_SOFTWARE);
85 	}
86 
87 	if(    (myMaskPtr[0] == '0')
88 	  	&& (myMaskPtr[1] =='x' || myMaskPtr[1] == 'X')
89 	  )
90 	{
91 
92 	  	if(
93 		 !(  (myMaskPtr[2] >= 'a' && myMaskPtr[2] <= 'f')
94 			 ||(myMaskPtr[2] >= 'A' && myMaskPtr[2] <= 'F')
95 			 ||(myMaskPtr[2] >= '0' && myMaskPtr[2] <= '9')
96 			 ) ||
97 		 !(  (myMaskPtr[3] >= 'a' && myMaskPtr[3] <= 'f')
98 			 ||(myMaskPtr[3] >= 'A' && myMaskPtr[3] <= 'F')
99 			 ||(myMaskPtr[3] >= '0' && myMaskPtr[3] <= '9')
100 			 ) ||
101 		 !(  (myMaskPtr[4] >= 'a' && myMaskPtr[4] <= 'f')
102 			 ||(myMaskPtr[4] >= 'A' && myMaskPtr[4] <= 'F')
103 			 ||(myMaskPtr[4] >= '0' && myMaskPtr[4] <= '9')
104 			 ) ||
105 		 !(  (myMaskPtr[5] >= 'a' && myMaskPtr[5] <= 'f')
106 			 ||(myMaskPtr[5] >= 'A' && myMaskPtr[5] <= 'F')
107 			 ||(myMaskPtr[5] >= '0' && myMaskPtr[5] <= '9')
108 			 ) ||
109 		 !(  (myMaskPtr[6] >= 'a' && myMaskPtr[6] <= 'f')
110 			 ||(myMaskPtr[6] >= 'A' && myMaskPtr[6] <= 'F')
111 			 ||(myMaskPtr[6] >= '0' && myMaskPtr[6] <= '9')
112 			 ) ||
113 		 !(  (myMaskPtr[7] >= 'A' && myMaskPtr[7] <= 'f')
114 			 ||(myMaskPtr[7] >= 'A' && myMaskPtr[7] <= 'F')
115 			 ||(myMaskPtr[7] >= '0' && myMaskPtr[7] <= '9')
116 			 ) ||
117 		 !(  (myMaskPtr[8] >= 'a' && myMaskPtr[8] <= 'f')
118 			 ||(myMaskPtr[8] >= 'A' && myMaskPtr[8] <= 'F')
119 			 ||(myMaskPtr[8] >= '0' && myMaskPtr[8] <= '9')
120 			 ) ||
121 		 !(  (myMaskPtr[9] >= 'a' && myMaskPtr[9] <= 'f')
122 			 ||(myMaskPtr[9] >= 'A' && myMaskPtr[9] <= 'F')
123 			 ||(myMaskPtr[9] >= '0' && myMaskPtr[9] <= '9')
124 			 ) ||
125 		 ( strlen(myMaskPtr) != 10)
126 		 )
127 		{
128 		  /*doesn't have all 8 hex chars*/
129 		  fprintf(stderr, "%s: \"%s\" is not a valid subnet mask!\n(Hex values need 8 chars [0-9][a-f][A-F])\n", PACKAGE, myMaskPtr);
130 		  return(EX_DATAERR);
131 		}
132 		else if( sscanf((char*)(myMaskPtr+2), "%08x", &myMask) != 1)
133 		{
134 		  /* hex conversion failed... weird. should not happen*/
135 		  fprintf(stderr, "%s: Stage two hex parsing failed! Please report this as a bug with the input that caused it.\n", PACKAGE);
136 		  return(EX_DATAERR);
137 		}
138     }
139 	else
140 	{
141 
142 
143 	  /* try to convert the octets for the mask - this also returns 1 if the conversion fails */
144 	  if(octets_to_u_int(&myMask, myMaskPtr))
145 		{
146 		  /*assume CIDR */
147 
148 		  if((strchr(myMaskPtr, '.') != NULL) || sscanf(myMaskPtr, "%" U_INT_32_PRINTF_STRING, &myCIDR) != 1)
149 			{
150 			  /* not CIDR */
151 			  fprintf(stderr, "%s: \"%s\" is not a valid subnet mask or wildcard bit mask!\n", PACKAGE, myMaskPtr);
152 			  return(EX_DATAERR);
153 			}
154 
155 
156 		  if(myCIDR > 32 )
157 			{
158 			  fprintf(stderr, "CIDR netmask notations must be between 0 and 32 bits inclusive!\n");
159 			  return(EX_DATAERR);
160 			}
161 		  /* Make a mask from the CIDR value */
162 		  myMask = bitfill_from_left(myCIDR);
163 
164 		}
165 	}
166 
167 	/* check the ip and subnet mask for class A, B, C requirments and warn if inconsistent */
168 	/*
169 	validate_class(myIp, myMask);
170 	*/
171 
172 	/* ip */
173 	u_int_to_octets(myIp, myIpStr);
174 
175 	/* netmask */
176 	if( validatemask(myMask) )
177 	{
178 		/* This failed but may be Cisco-style */
179 		/* not it so we can see if it is cisco-style */
180 		myMask = ~myMask;
181 
182 		if( validatemask(myMask) )
183 		{
184 			/* Now we know it's bad */
185 			fprintf(stderr, "%s: \"%s\" is not a valid subnet mask or wildcard bit mask!\n", PACKAGE, myMaskPtr);
186 			return(EX_DATAERR);
187 		}
188 	}
189 
190 	u_int_to_octets(myMask, myMaskStr);
191 
192 	/* Wildcard bits as string */
193 	u_int_to_octets(~myMask, myWildcardStr);
194 
195 	/* CIDR as a string */
196 	myCIDR = (unsigned int)bitcount(myMask);
197 	snprintf(myCIDRStr, BIT_LEN, "%" U_INT_32_PRINTF_STRING, myCIDR );
198 
199 	/* network address */
200 	myNt = (myIp & myMask);
201 	u_int_to_octets( myNt, myNtStr);
202 
203 	/* Broadcast address */
204 	myBr = ( myNt + ~myMask );
205 	u_int_to_octets(  myBr, myBrStr) ;
206 
207 	/* usable ips */
208 	usableIps = (myCIDR >30)?0:(myBr - myNt - 1);
209 
210 	if(usableIps <= 0)
211 	{
212 		strcpy(myStartIpStr , "<none>");
213 		strcpy(myEndIpStr , "<none>");
214 	}
215 	else
216 	{
217 		/* startIp */
218 		u_int_to_octets( myNt + 1, myStartIpStr);
219 
220 		/* endIp */
221 		u_int_to_octets( myBr - 1, myEndIpStr);
222 	}
223 
224 	whatnet_printdata( myMask, myIpStr, myMaskStr, myWildcardStr, myCIDRStr, myNtStr, myBrStr, myStartIpStr, myEndIpStr, usableIps );
225 
226 	return(0);
227 }
228 
229