OSDN Git Service

Ver1.5.28 Changed to deny duplicated open, added udp send and ohters.
[opengate/opengate.git] / opengate / opengatesrv / comm-ip6fw.c
1 /**************************************************
2 opengate server
3  module for Controling ipfw for IPv6 address 
4
5 Copyright (C) 2005 Opengate Project Team
6 Written by Katsuhiko Eguchi, 2005 
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21
22 Email: watanaby@is.saga-u.ac.jp
23 **************************************************/
24
25 #include "opengatesrv.h"
26
27 char ruleNumber6[WORDMAXLN];  /* ipfw rule number in string form */
28
29 int getRuleNumber6(char *clientAddr6);
30 int GetRuleNumber6(char *clientAddr6);
31
32 static void sigFunc(int signo);
33
34 /******************************************************************/
35 /* open gate for clientAddr6 (nnnn:nnnn::nnnn:nnnn)               */
36 /******************************************************************/
37 int openClientGate6(char *clientAddr6, char *userid, char *macAddr6, char *userProperty)
38 {
39   int fd;
40   int ret=0;
41   int retNum;
42
43   Sigfunc *defaultSigFunc;
44
45   /* exclusive exec of ipfw to avoid duplicated rule number */
46
47   /**** prepare ****/
48   /* open lockfile */
49   fd=open(GetConfValue("LockFile"), O_RDWR|O_CREAT, 
50           S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
51   if(fd==-1){
52     err_msg("ERR at %s#%d: lockfile open error",__FILE__,__LINE__);
53     return 1;
54   } 
55
56   /* set timeout */
57   if((defaultSigFunc=Signal(SIGALRM, sigFunc))==SIG_ERR) return 1;
58   alarm(atoi(GetConfValue("LockTimeout")));
59
60   /* lock */
61   if(Lock(fd)<0){
62     err_msg("ERR at %s#%d: lock error",__FILE__,__LINE__);
63     return 1;
64   }
65
66   /* reset timeout */
67   Signal(SIGALRM, defaultSigFunc);
68   alarm(0);
69
70   /**** read rules ****/
71   if((retNum=GetRuleNumber6(clientAddr6))<0){
72     Unlock(fd);
73     Close(fd);
74     return retNum;
75   }
76
77   /**** write rules ****/
78   if(atoi(GetConfValue("IpfwScript/Enable"))){
79     /********** use perl script to control firewall ************/
80
81     if(Systeml(1, GetConfValue("IpfwScript/Path"),GetConfValue("IpfwPath"),
82                ruleNumber6,clientAddr6,
83                userid,macAddr6,userProperty,
84                GetConfValue("IpfwTagNumber"),(char *)0) != 0){
85       err_msg("ERR at %s#%d: exec ipfw script error",__FILE__,__LINE__);
86       ret=1; /* abmormal */
87     }
88   }
89   else{
90     /********** direct control of firewall **********************/
91     /********** add outgoing ipfw rule for the client *************/
92     if(Systeml(1, GetConfValue("IpfwPath"),"-q","add",ruleNumber6,
93                "count","tag",GetConfValue("IpfwTagNumber"),
94                "ip","from",clientAddr6,"to","any",
95                "//", userid, (char *)0) != 0){
96               err_msg("ERR at %s#%d: exec ipfw add error",__FILE__,__LINE__);
97               ret=1;
98     }
99
100     /********** add incoming ipfw rule for the client *************/
101     if(Systeml(1, GetConfValue("IpfwPath"),"-q","add",ruleNumber6,
102                "count","tag",GetConfValue("IpfwTagNumber"),
103                "ip","from","any","to",clientAddr6,
104                "//", userid, (char *)0) != 0){
105               err_msg("ERR at %s#%d: exec ipfw add error",__FILE__,__LINE__);
106               ret=1; /* abnormal */
107     }
108   }
109
110   /* uplock */
111   Unlock(fd);
112   Close(fd);
113
114   return ret;
115 }
116
117
118 /******************************************************************/
119 /* close gate for clientAddr (nnnn:nnnn:nnnn::nnnn:nnnn:nnnn)     */
120 /******************************************************************/
121 void closeClientGate6(struct clientAddr *pClientAddr, char *userid, char *macAddr6)
122 {
123   double time_l;
124   int hour, min, sec;
125   time_t timeOut;
126   
127   /********** del ipfw rule for the client *************/
128   DelIp6fwRule(pClientAddr->ruleNumber);
129   
130   timeOut = time(NULL);
131   time_l=difftime(timeOut,pClientAddr->timeIn);
132   hour=time_l/60/60;
133   min=(time_l-hour*60*60)/60;
134   sec=(time_l-hour*60*60-min*60);
135   err_msg("CLOS: user %s from %s at %s ( %02d:%02d:%02d )",
136           userid, pClientAddr->ipAddr, macAddr6, hour,min,sec);
137
138   /* send message to opengatemd server to renew the info in md cache */
139   PutMacAddressToOpengateMd(macAddr6);
140  
141   return;
142 }
143
144
145 /***********************************************/
146 /* delete ipfw rule                            */
147 /***********************************************/
148 void delIp6fwRule(char *ruleNumber)
149 {
150   int ruleCount;
151
152   /* get rule count */
153   ruleCount = CountRuleNumber6(ruleNumber);
154
155   /* delete rule */
156   if(ruleCount>0){
157     if(Systeml(1, GetConfValue("IpfwPath"),"delete",ruleNumber,(char *)0) != 0){
158       err_msg("ERR at %s#%d: exec ipfw del error",__FILE__,__LINE__);
159     }
160   }
161 }
162   
163 /**************************************/
164 /* get unused ipfw rule number        */
165 /* error if addr is already in rules */ 
166 /* return value ret>0: acquired rule number that can be used */
167 /*              ret=-1: no rule number available */
168 /*              ret=-2: some system error occured */
169 /*              ret=-num: the ip address is already registered in rule 'num' */
170 /**************************************/
171 int getRuleNumber6(char *clientAddr6)
172 {
173   FILE *fpipe;
174   char buf[BUFFMAXLN];
175   int num,newNum,readinNum;
176     char *p;
177   int ip6fwmin;
178   int ip6fwmax;
179   int ip6fwinterval;
180   int portStatus;
181   int fileStatus;
182   enum status {NORMAL, ABNORMAL, FOUND, NOTFOUND, DUP};
183
184   if((fpipe=Popenl(1, "r", GetConfValue("IpfwPath"),"list",(char *)0)) == NULL){ 
185       err_msg("ERR at %s#%d: exec ipfw list error",__FILE__,__LINE__);
186   }
187   
188   /* search unused rule number in the list read from pipe */
189   /* check duplication of clientAddr to existing rules */
190
191   newNum=-1;
192   readinNum=0;
193   portStatus=NOTFOUND;
194   fileStatus=NORMAL;
195
196   /* get rule range from config */
197   ip6fwmin=atoi(GetConfValue("IpfwRule/Min"));
198   ip6fwmax=atoi(GetConfValue("IpfwRule/Max"));
199   ip6fwinterval=atoi(GetConfValue("IpfwRule/Interval"));
200
201   /* each port is checked whether it can be used for new rule or not */
202   for(num=ip6fwmin;num<=ip6fwmax;num+=ip6fwinterval){
203
204     /* skip rules smaller than num */
205     while(readinNum<num){
206       if(fgets(buf, BUFFMAXLN, fpipe)==NULL){
207         if(feof(fpipe)==1) fileStatus=EOF; 
208         else fileStatus=ABNORMAL;
209         break;
210       }
211       if( sscanf(buf, "%d", &readinNum) !=1 ){
212         err_msg("ERR at %s#%d: abnormal ipfw response[ %s ]",
213                 __FILE__,__LINE__,buf);
214         fileStatus=ABNORMAL; /* abnormal responsem exit internal loop */
215         break;
216       }
217     }
218       
219     if(fileStatus==ABNORMAL){
220       /* abnormal file proc, exit external loop */ 
221       break;
222     }
223
224     if(fileStatus==EOF){
225       /* EOF before reading a rule that is larger or equal to num */
226       /* it means that num can be used for new client */
227       portStatus=FOUND;
228       newNum=num;
229       break;
230     }
231
232     /* at this point, readinNum is larger or equal to num */
233     /* check number duplication */
234     if(readinNum==num){
235
236       /* if clientAddr is found in the existing rule, then err exit. */
237       if(((p=(char*)strstr(buf+1,clientAddr6))!=NULL)
238          && isspace(*(p-1))
239          && !isalnum(*(p+strlen(clientAddr6)))){
240         /* the clientAddr is found in the rule num */
241         newNum=num;
242         portStatus=DUP;
243         break;
244       }
245       /* the num is used for other client */
246       /* go to checking of next num */
247       else{
248         continue;
249       }
250     }
251    
252     /* at this point, readNum is larger than num */
253     /* it means that num can be used for new client */
254     newNum=num;
255     portStatus=FOUND;
256     break;
257   }
258   
259   /* close pipe */
260   Pclose(fpipe);
261
262   if(fileStatus==ABNORMAL){
263     err_msg("ERR at %s#%d: abnormal ipfw response ",__FILE__,__LINE__);
264     return -2;
265   }
266   if(portStatus==NOTFOUND){
267     err_msg("ERR at %s#%d: cannot get unused ipfw number",__FILE__,__LINE__);
268     return -1;
269   }
270   if(portStatus==DUP){
271     snprintf(ruleNumber6, WORDMAXLN, "%d", newNum); /* to string */
272     return -newNum;
273   }
274
275   snprintf(ruleNumber6, WORDMAXLN, "%d", newNum); /* to string */
276
277   return newNum;
278 }
279
280 /*******************************/
281 /* get packet count from ipfw  */
282 /*******************************/
283 int getPacketCount6(char *ruleNumber)
284 {
285   FILE *fpipe;
286   char buf[BUFFMAXLN];
287   int rule;
288   int packets,packetsSum;
289
290   /* exec proc */
291   if((fpipe=Popenl(1, "r", GetConfValue("IpfwPath"),"-a","list",ruleNumber,(char *)0)) == NULL){ 
292     err_msg("ERR at %s#%d: exec ipfw -a list error",__FILE__,__LINE__);
293     return 0; /* abnormal */
294   }
295   
296   /* search unused number in the list read from pipe */
297   packetsSum=0;
298     
299   while(fgets(buf, BUFFMAXLN, fpipe)!=NULL){
300     sscanf(buf, "%d %d", &rule, &packets);   /* get packet count */
301     packetsSum+=packets;
302   }
303
304   /* close pipe */
305   Pclose(fpipe);
306
307   return packetsSum;
308 }
309
310 /**********************************************/
311 /* get rule count registed to a rule number   */
312 /**********************************************/
313 int countRuleNumber6(char *ruleNumber)
314 {
315   FILE *fpipe;
316   char buf[BUFFMAXLN];
317   int ruleCount;
318
319   /* exec proc */
320   if((fpipe=Popenl(1, "r", GetConfValue("IpfwPath"),"list",ruleNumber,(char *)0)) == NULL){ 
321     err_msg("ERR at %s#%d: exec ipfw list error",__FILE__,__LINE__);
322   }
323   
324   /* count line read from pipe */
325   ruleCount = 0;
326   while(fgets(buf, BUFFMAXLN, fpipe)!=0) ruleCount++;
327
328   /* close pipe */
329   Pclose(fpipe);
330
331   return ruleCount;
332 }
333
334 /**********************************************/
335 /* function called by signal int              */
336 /**********************************************/
337 static void sigFunc(int signo)
338 {
339   return;
340 }
341
342 /**********************************************/
343 /**********************************************/
344
345 int GetRuleNumber6(char *clientAddr6)
346 {
347   int ret;
348
349   if(debug>1) err_msg("DEBUG:=>getRuleNumber6(%s)",clientAddr6);
350   ret=getRuleNumber6(clientAddr6);
351   if(debug>1) err_msg("DEBUG:(%d)<=getRuleNumber6( )",ret);
352
353   return ret;
354 }
355
356 int OpenClientGate6(char *clientAddr6, char *userid, char *macAddr6, char *userProperty)
357 {
358   int ret;
359
360   if(debug>1) err_msg("DEBUG:=>openClientGate6(%s,%s,%s,%s)",clientAddr6,userid,macAddr6,userProperty);
361   ret=openClientGate6(clientAddr6, userid, macAddr6, userProperty);
362   if(debug>1) err_msg("DEBUG:(%d)<=openClientGate6( )",ret);
363
364   return ret;
365 }
366
367 void CloseClientGate6(struct clientAddr *pClientAddr, char *userid, char *macAddr6)
368 {
369   if(debug>1) err_msg("DEBUG:=>closeClientGate6(%p,%s,%s)",pClientAddr,userid,macAddr6);
370   closeClientGate6(pClientAddr,userid,macAddr6);
371   if(debug>1) err_msg("DEBUG:<=closeClientGate6( )");
372 }
373
374 int GetPacketCount6(char *ruleNumber)
375 {
376   int ret;
377
378   if(debug>1) err_msg("DEBUG:=>getPacketCount6(%s)",ruleNumber);
379   ret=getPacketCount6(ruleNumber);
380   if(debug>1) err_msg("DEBUG:(%d)<=getPacketCount6( )",ret);
381
382   return ret;
383 }
384
385 int CountRuleNumber6(char *ruleNumber)
386 {
387   int ret;
388   
389   if(debug>1) err_msg("DEBUG:=>countRuleNumber6(%s)", ruleNumber);
390   ret=countRuleNumber6(ruleNumber);
391   if(debug>1) err_msg("DEBUG:(%d)<=countRuleNumber6( )",ret);
392   
393   return ret;
394 }
395
396 void DelIp6fwRule(char *ruleNumber){
397   if(debug>1) err_msg("DEBUG:=>delIp6fwRule(%s)",ruleNumber);
398   delIp6fwRule(ruleNumber);
399   if(debug>1) err_msg("DEBUG:<=delIp6fwRule( )");
400 }