1 /**************************************************
3 module for Controling ipfw
5 Copyright (C) 1999 Opengate Project Team
6 Written by Yoshiaki Watanabe
7 Modified Katsuhiko Eguchi, 2005
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 Email: watanaby@is.saga-u.ac.jp
24 **************************************************/
26 #include "opengatesrv.h"
28 char ruleNumber4[WORDMAXLN]; /* ipfw rule number in string form */
30 int getRuleNumber4(char *clientAddr4);
31 int GetRuleNumber4(char *clientAddr4);
33 static void sigFunc(int signo);
35 /******************************************************************/
36 /* open gate for clientAddr4 (nnn.nnn.nnn.nnn) */
37 /******************************************************************/
38 int openClientGate4(char *clientAddr4, char *userid, char *macAddr4, char *userProperty)
44 Sigfunc *defaultSigFunc;
46 /* exclusive exec of ipfw to avoid overlapped rule number */
49 fd=open(GetConfValue("LockFile"), O_RDWR|O_CREAT,
50 S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
52 err_msg("ERR at %s#%d: lockfile open error",__FILE__,__LINE__);
57 if((defaultSigFunc=Signal(SIGALRM, sigFunc))==SIG_ERR) return 1;
58 alarm(atoi(GetConfValue("LockTimeout")));
62 err_msg("ERR at %s#%d: lock error",__FILE__,__LINE__);
67 Signal(SIGALRM, defaultSigFunc);
70 /**** read rules ****/
71 if((retNum=GetRuleNumber4(clientAddr4))<0){
72 /* fail then unlock */
78 /**** write rules ****/
80 if(atoi(GetConfValue("IpfwScript/Enable"))){
81 /********** use perl script to control firewall ************/
83 if(Systeml(GetConfValue("IpfwScript/Path"),GetConfValue("IpfwPath"),
84 ruleNumber4,clientAddr4,
85 userid,macAddr4,userProperty,(char *)0) != 0){
86 err_msg("ERR at %s#%d: exec script error",__FILE__,__LINE__);
90 /* lock is not necessary in following exec */
92 Close(fd); /* because reserved number is used */
95 /********** direct control of firewall **********************/
96 /********** add outgoing ipfw rule for the client *************/
97 if(Systeml(GetConfValue("IpfwPath"),"-q","add",ruleNumber4,"allow","ip",
98 "from",clientAddr4,"to","any",(char *)0) != 0){
99 err_msg("ERR at %s#%d: exec ipfw add error",__FILE__,__LINE__);
100 ret=1; /* abnormal */
103 /* lock is not necessary in following exec */
105 Close(fd); /* because reserved number is used */
107 if(Systeml(GetConfValue("IpfwPath"),"-q","add",ruleNumber4,"allow","ip",
108 "from","any","to",clientAddr4,(char *)0) != 0){
109 err_msg("ERR at %s#%d: exec ipfw add error",__FILE__,__LINE__);
110 ret=1; /* abnormal */
117 /******************************************************************/
118 /* close gate for clientAddr (nnn.nnn.nnn.nnn) */
119 /******************************************************************/
120 void closeClientGate4(struct clientAddr *pClientAddr, char *userid, char *macAddr4)
126 /********** del ipfw rule for the client *************/
127 DelIpfwRule(pClientAddr->ruleNumber);
129 timeOut = time(NULL);
130 time_l=difftime(timeOut,pClientAddr->timeIn);
132 min=(time_l-hour*60*60)/60;
133 sec=(time_l-hour*60*60-min*60);
134 err_msg("CLOS: user %s from %s at %s ( %02d:%02d:%02d )",
135 userid, pClientAddr->ipAddr, macAddr4, hour,min,sec);
140 /***********************************************/
141 /* delete ipfw rule */
142 /***********************************************/
143 void delIpfwRule(char *ruleNumber){
147 count=CountRuleNumber4(ruleNumber);
151 /* [ipfw del rule] deletes all rule of the rule number at one call */
152 if(Systeml(GetConfValue("IpfwPath"),"del",ruleNumber,(char *)0) != 0){
153 err_msg("ERR at %s#%d: exec ipfw del error",__FILE__,__LINE__);
158 /**************************************/
159 /* get unused ipfw rule number */
160 /* error if addr is already in rules */
161 /* return value ret>0: acquired rule number that can be used */
162 /* ret=-1: no rule number available */
163 /* ret=-2: some system error occured */
164 /* ret=-num: the ip address is already registered in rule 'num' */
165 /**************************************/
166 int getRuleNumber4(char *clientAddr4)
170 int num,newNum,readinNum;
177 enum status {NORMAL, ABNORMAL, FOUND, NOTFOUND, DUPLICATED};
179 /* exec ipfw list and open pipe */
180 if((fpipe=Popenl("r", GetConfValue("IpfwPath"),"list",(char *)0)) == NULL){
181 err_msg("ERR at %s#%d: exec ipfw list error",__FILE__,__LINE__);
184 /* search unused rule number in the list read from pipe */
185 /* check duplication of clientAddr to existing rules */
192 /* get rule range from config */
193 ipfwmin=atoi(GetConfValue("IpfwRule/Min"));
194 ipfwmax=atoi(GetConfValue("IpfwRule/Max"));
195 ipfwinterval=atoi(GetConfValue("IpfwRule/Interval"));
197 /* each port is checked whether it can be used for new rule or not */
198 for(num=ipfwmin;num<=ipfwmax;num+=ipfwinterval){
200 /* skip rules smaller than num */
201 while(readinNum<num){
202 if(fgets(buf, BUFFMAXLN, fpipe)==NULL){
203 if(feof(fpipe)==1) fileStatus=EOF;
204 else fileStatus=ABNORMAL;
207 if( sscanf(buf, "%d", &readinNum) !=1 ){
208 err_msg("ERR at %s#%d: abnormal ipfw response[ %s ]",
209 __FILE__,__LINE__, buf);
210 fileStatus=ABNORMAL; /* abnormal responsem exit internal loop */
215 if(fileStatus==ABNORMAL){
216 /* abnormal file proc, exit external loop */
221 /* EOF before reading a rule that is larger or equal to num */
222 /* it means that num can be used for new client */
228 /* at this point, readinNum is larger or equal to num */
229 /* check number duplication */
232 /* if clientAddr is found in the existing rule, then err exit. */
233 if(((p=(char*)strstr(buf+1,clientAddr4))!=NULL)
235 && !isalnum(*(p+strlen(clientAddr4)))){
236 err_msg("ERR at %s#%d: overlapped request from %s",
237 __FILE__,__LINE__, clientAddr4);
239 portStatus=DUPLICATED;
242 /* the num is used for other client */
243 /* go to checking of next num */
249 /* at this point, readNum is larger than num */
250 /* it means that num can be used for new client */
259 if(fileStatus==ABNORMAL){
260 err_msg("ERR at %s#%d: abnormal ipfw response ",__FILE__,__LINE__);
263 if(portStatus==NOTFOUND){
264 err_msg("ERR at %s#%d: cannot get unused ipfw number",__FILE__,__LINE__);
267 if(portStatus==DUPLICATED){
271 snprintf(ruleNumber4, WORDMAXLN, "%d", newNum); /* to string */
276 /*******************************/
277 /* get packet count from ipfw */
278 /*******************************/
279 int getPacketCount4(char *ruleNumber)
284 int packets,packetsSum;
287 if((fpipe=Popenl("r", GetConfValue("IpfwPath"),"-a","list",ruleNumber,(char *)0)) == NULL){
288 err_msg("ERR at %s#%d: exec ipfw -a list error",__FILE__,__LINE__);
291 /* search unused number in the list read from pipe */
294 while(fgets(buf, BUFFMAXLN, fpipe)!=NULL){
295 sscanf(buf, "%d %d", &rule, &packets); /* get packet count */
305 /**********************************************/
306 /* get rule count registed to a rule number */
307 /**********************************************/
308 int countRuleNumber4(char *ruleNumber)
315 if((fpipe=Popenl("r", GetConfValue("IpfwPath"),"list",ruleNumber,(char *)0)) == NULL){
316 err_msg("ERR at %s#%d: exec ipfw list error",__FILE__,__LINE__);
319 /* count line read from pipe */
321 while(fgets(buf, BUFFMAXLN, fpipe)!=0) ruleCount++;
329 /**********************************************/
330 /* function called by signal int */
331 /**********************************************/
332 static void sigFunc(int signo)
337 /**********************************************/
338 /**********************************************/
339 int GetRuleNumber4(char *clientAddr4)
343 if(debug>1) err_msg("DEBUG:=>getRuleNumber4(%s)",clientAddr4);
344 ret=getRuleNumber4(clientAddr4);
345 if(debug>1) err_msg("DEBUG:(%d)<=getRuleNumber4( )",ret);
350 int OpenClientGate4(char *clientAddr4, char *userid, char *macAddr4, char *userProperty)
354 if(debug>1) err_msg("DEBUG:=>openClientGate4(%s,%s,%s,%s)",clientAddr4,userid,macAddr4,userProperty);
355 ret=openClientGate4(clientAddr4, userid, macAddr4, userProperty);
356 if(debug>1) err_msg("DEBUG:(%d)<=openClientGate4( )",ret);
361 void CloseClientGate4(struct clientAddr *pClientAddr, char *userid, char *macAddr4)
363 if(debug>1) err_msg("DEBUG:=>closeClientGate4(%p,%s,%s)",pClientAddr,userid,macAddr4);
364 closeClientGate4(pClientAddr,userid,macAddr4);
365 if(debug>1) err_msg("DEBUG:<=closeClientGate4( )");
369 int GetPacketCount4(char *ruleNumber)
373 if(debug>1) err_msg("DEBUG:=>getPacketCount4(%s)",ruleNumber);
374 ret=getPacketCount4(ruleNumber);
375 if(debug>1) err_msg("DEBUG:(%d)<=getPacketCount4( )",ret);
380 void DelIpfwRule(char *ruleNumber){
381 if(debug>1) err_msg("DEBUG:=>delIpfwRule(%s)",ruleNumber);
382 delIpfwRule(ruleNumber);
383 if(debug>1) err_msg("DEBUG:<=delIpfwRule( )");
386 int CountRuleNumber4(char *ruleNumber)
390 if(debug>1) err_msg("DEBUG:=>countRuleNumber4(%s)", ruleNumber);
391 ret=countRuleNumber4(ruleNumber);
392 if(debug>1) err_msg("DEBUG:(%d)<=countRuleNumber4( )",ret);