1 /**************************************************
2 OpengateM - a MAC address authentication system
3 module for checking TTL(TimeToLive) (or hlim in ipv6) to detect router
4 defaut TTL has some fixed value (depending OS).
5 and it is decrement at passing the router/NAT.
7 Copyright (C) 2011 Opengate Project Team
8 Written by Yoshiaki Watanabe
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 Email: watanaby@is.saga-u.ac.jp
25 **************************************************/
26 #include "opengatemd.h"
29 unsigned long subnetBits;
34 static char validInitialTtl[256];
35 static struct SubnetSet* pSubnet;
38 /**********************************
39 initialize ttl check routine
40 **********************************/
41 int initTtlCheck(void){
47 struct SubnetSet* pNext;
48 unsigned long subnetBits;
54 /***** ttl table setting ******/
55 /* initial values of table is false */
56 for(i=0; i<256; i++) validInitialTtl[i] = FALSE;
58 /* get string for initial ttls from conf file, eg:[64 128 255] */
59 pStart = GetConfValue("ValidInitialTtl");
60 if(isNull(pStart)) return FALSE;
62 /* loop for setting ttl table */
65 /* get number and set table entry */
66 if(sscanf(pStart, "%d", &ttlValue)==1){
67 validInitialTtl[ttlValue]=TRUE;
70 /* set next scan point */
71 pStart = strchr(pStart+1, ' ');
72 if(isNull(pStart)) break;
75 /******** subnet setting ***********/
76 /* count subnet setting */
78 subnetStr=GetFirstConfValue("SubnetHopCount");
79 while(!isNull(subnetStr)){
81 subnetStr=GetNextConfValue();
84 /* get memory for the setting */
85 pSubnet=malloc(sizeof(struct SubnetSet)*(nSubnet));
88 /*loop all subnet setting */
89 subnetStr=GetFirstConfValue("SubnetHopCount");
90 while(!isNull(subnetStr)){
92 /* get address and hop count defined as [192.168.1.0/24 1] */
93 if(sscanf(subnetStr, "%d.%d.%d.%d/%d %d",
94 &byte[0], &byte[1], &byte[2], &byte[3],
95 &maskLength, &hopCount)==6){
97 /* sum up address bytes to a long int */
100 subnetBits = subnetBits<<8;
101 subnetBits += byte[i];
104 /* save subnet setting to malloc area */
105 pNext->subnetBits=subnetBits;
106 if(maskLength<=32) pNext->maskLength=maskLength;
107 else pNext->maskLength=0;
108 pNext->hopCount=hopCount;
110 /* goto next store area */
114 /* get next subnet setting */
115 subnetStr=GetNextConfValue();
121 /*********************************
122 check ttl for detecting access via nat/router
123 *********************************/
124 int isSentViaNatOrRouter(char* ipAddress, char* macAddress, int ttl){
126 unsigned int byte[4]; /* 4 bytes representing given ipv4 address */
127 unsigned long addressBits=0;
128 unsigned long subnetMask=0;
131 struct SubnetSet* pNext;
134 /* if ttl is valid initial ttl then no router/nat */
135 if( validInitialTtl[ttl] ) return 0; /* no router/nat */
137 /* if ipv6, the nat/router is assumed as a router */
138 if( strchr(ipAddress, ':')!=NULL){
139 if( validInitialTtl[ttl] ) return 0; /* direct (no router/nat) */
140 else return 2; /* router */
143 /* if ipv4, calculate initial ttl as (present ttl)+(router hops) */
144 /* and compare to the router hop setting in conf file */
145 /* get 4 bytes of ipv4 address */
146 if(sscanf(ipAddress, "%d.%d.%d.%d",
147 &byte[0], &byte[1], &byte[2], &byte[3])!=4) return -1;/*error */
149 /* sum up address bytes to a long int */
152 addressBits = addressBits<<8;
153 addressBits += byte[i];
156 /* check each subnet setting */
160 for(i=0; i<nSubnet; i++){
162 /* compare subnet and address */
163 /* subnetBits 1011 0011 1100 0011 0000 */
164 /* addressBits 1011 0011 0110 0011 1100 */
165 /* Bit XOR 0000 0000 1010 0000 1100 */
166 /* subnet mask 1111 1111 1111 1111 0000 */
167 /* Bit AND 0000 0000 1010 0000 0000 */
168 /* If result is all-zero, the address is in the subnet */
169 subnetMask=0xFFFFFFFF<<(32 - (pNext->maskLength));
170 if(!( ((pNext->subnetBits)^addressBits) & subnetMask )){
172 /* if the address is included in subnet having longest mask */
173 /* save the hop count */
174 if((pNext->maskLength) > maxMaskLength){
175 maxMaskLength = pNext->maskLength;
176 hopSave = pNext->hopCount;
180 /* get next SubnetHopCount */
184 /* add hop to ttl, then compare to valid initial ttl */
185 if( hopSave<0 || (ttl+hopSave)>=256 ) return ERROR; /* error */
186 if( validInitialTtl[ttl+hopSave] ){
187 if(hopSave==0) return NONAT; /* no nat/router */
188 else return ROUTER; /* valid router */
190 return NAT; /* unknown nat or router inserted */
193 /***********************************************
194 putout log at nat/router detection
195 isNatOrRouter:1=UnknownNatOrRouter, 2=FormalRouterOnly, 0=None, -1=err
196 **********************************************/
197 void putLogAtNatOrRouter(int isNatOrRouter, char* ipAddress, char* macAddress, int ttl){
199 if(isNatOrRouter==1 && atoi(GetConfValue("ShowNat"))){
200 err_msg("INFO : packet is sent via unknown nat/router[%s][%s][%d]",
201 ipAddress, macAddress, ttl);
203 if(isNatOrRouter==2 && atoi(GetConfValue("ShowRouter"))){
204 err_msg("INFO : packet is sent via formal router[%s][%s][%d]",
205 ipAddress, macAddress, ttl);
209 /***********************************************
210 routines for debugging output
211 **********************************************/
212 int InitTtlCheck(void){
214 if(debug>1) err_msg("DEBUG:=>initTtlCheck( )");
215 ret = initTtlCheck();
216 if(debug>1) err_msg("DEBUG:(%d)<=initTtlCheck( )",ret);
220 int IsSentViaNatOrRouter(char* ipAddress, char* macAddress, int ttl){
222 if(debug>2) err_msg("DEBUG:=>isSentViaNatOrRouter(%s,%s,%d)", ipAddress, macAddress, ttl);
223 ret = isSentViaNatOrRouter(ipAddress, macAddress, ttl);
224 if(debug>2) err_msg("DEBUG:(%d)<=isSentViaNatOrRouter( )", ret);
228 void PutLogAtNatOrRouter(int isNatOrRouter, char* ipAddress, char* macAddress, int ttl){
229 if(debug>2) err_msg("DEBUG:=>putLogAtNatOrRouter(%d,%s,%s,%d)",
230 isNatOrRouter,ipAddress,macAddress,ttl);
231 putLogAtNatOrRouter(isNatOrRouter,ipAddress,macAddress,ttl);
232 if(debug>2) err_msg("DEBUG:(%d)<=putLOgAtNatOrRouter( )");
237 /**************test main********************
241 ******************************************/