1 /**************************************************
3 module for Controling ipfw for IPv6 address
5 Copyright (C) 2005 Opengate Project Team
6 Written by Katsuhiko Eguchi, 2005
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.
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.
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.
22 Email: watanaby@is.saga-u.ac.jp
23 **************************************************/
25 #include "opengatesrv.h"
27 char ruleNumber6[WORDMAXLN]; /* ipfw rule number in string form */
29 int getRuleNumber6(char *clientAddr6);
30 int GetRuleNumber6(char *clientAddr6);
32 static void sigFunc(int signo);
34 /******************************************************************/
35 /* open gate for clientAddr6 (nnnn:nnnn::nnnn:nnnn) */
36 /******************************************************************/
37 int openClientGate6(char *clientAddr6, char *userid, char *macAddr6, char *userProperty)
43 Sigfunc *defaultSigFunc;
45 /* exclusive exec of ipfw to avoid duplicated 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=GetRuleNumber6(clientAddr6))<0){
77 /**** write rules ****/
78 if(atoi(GetConfValue("IpfwScript/Enable"))){
79 /********** use perl script to control firewall ************/
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__);
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__);
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 */
118 /******************************************************************/
119 /* close gate for clientAddr (nnnn:nnnn:nnnn::nnnn:nnnn:nnnn) */
120 /******************************************************************/
121 void closeClientGate6(struct clientAddr *pClientAddr, char *userid, char *macAddr6)
127 /********** del ipfw rule for the client *************/
128 DelIp6fwRule(pClientAddr->ruleNumber);
130 timeOut = time(NULL);
131 time_l=difftime(timeOut,pClientAddr->timeIn);
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);
138 /* send message to opengatemd server to renew the info in md cache */
139 PutMacAddressToOpengateMd(macAddr6);
145 /***********************************************/
146 /* delete ipfw rule */
147 /***********************************************/
148 void delIp6fwRule(char *ruleNumber)
153 ruleCount = CountRuleNumber6(ruleNumber);
157 if(Systeml(1, GetConfValue("IpfwPath"),"delete",ruleNumber,(char *)0) != 0){
158 err_msg("ERR at %s#%d: exec ipfw del error",__FILE__,__LINE__);
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)
175 int num,newNum,readinNum;
182 enum status {NORMAL, ABNORMAL, FOUND, NOTFOUND, DUP};
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__);
188 /* search unused rule number in the list read from pipe */
189 /* check duplication of clientAddr to existing rules */
196 /* get rule range from config */
197 ip6fwmin=atoi(GetConfValue("IpfwRule/Min"));
198 ip6fwmax=atoi(GetConfValue("IpfwRule/Max"));
199 ip6fwinterval=atoi(GetConfValue("IpfwRule/Interval"));
201 /* each port is checked whether it can be used for new rule or not */
202 for(num=ip6fwmin;num<=ip6fwmax;num+=ip6fwinterval){
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;
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 */
219 if(fileStatus==ABNORMAL){
220 /* abnormal file proc, exit external loop */
225 /* EOF before reading a rule that is larger or equal to num */
226 /* it means that num can be used for new client */
232 /* at this point, readinNum is larger or equal to num */
233 /* check number duplication */
236 /* if clientAddr is found in the existing rule, then err exit. */
237 if(((p=(char*)strstr(buf+1,clientAddr6))!=NULL)
239 && !isalnum(*(p+strlen(clientAddr6)))){
240 /* the clientAddr is found in the rule num */
245 /* the num is used for other client */
246 /* go to checking of next num */
252 /* at this point, readNum is larger than num */
253 /* it means that num can be used for new client */
262 if(fileStatus==ABNORMAL){
263 err_msg("ERR at %s#%d: abnormal ipfw response ",__FILE__,__LINE__);
266 if(portStatus==NOTFOUND){
267 err_msg("ERR at %s#%d: cannot get unused ipfw number",__FILE__,__LINE__);
271 snprintf(ruleNumber6, WORDMAXLN, "%d", newNum); /* to string */
275 snprintf(ruleNumber6, WORDMAXLN, "%d", newNum); /* to string */
280 /*******************************/
281 /* get packet count from ipfw */
282 /*******************************/
283 int getPacketCount6(char *ruleNumber)
288 int packets,packetsSum;
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 */
296 /* search unused number in the list read from pipe */
299 while(fgets(buf, BUFFMAXLN, fpipe)!=NULL){
300 sscanf(buf, "%d %d", &rule, &packets); /* get packet count */
310 /**********************************************/
311 /* get rule count registed to a rule number */
312 /**********************************************/
313 int countRuleNumber6(char *ruleNumber)
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__);
324 /* count line read from pipe */
326 while(fgets(buf, BUFFMAXLN, fpipe)!=0) ruleCount++;
334 /**********************************************/
335 /* function called by signal int */
336 /**********************************************/
337 static void sigFunc(int signo)
342 /**********************************************/
343 /**********************************************/
345 int GetRuleNumber6(char *clientAddr6)
349 if(debug>1) err_msg("DEBUG:=>getRuleNumber6(%s)",clientAddr6);
350 ret=getRuleNumber6(clientAddr6);
351 if(debug>1) err_msg("DEBUG:(%d)<=getRuleNumber6( )",ret);
356 int OpenClientGate6(char *clientAddr6, char *userid, char *macAddr6, char *userProperty)
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);
367 void CloseClientGate6(struct clientAddr *pClientAddr, char *userid, char *macAddr6)
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( )");
374 int GetPacketCount6(char *ruleNumber)
378 if(debug>1) err_msg("DEBUG:=>getPacketCount6(%s)",ruleNumber);
379 ret=getPacketCount6(ruleNumber);
380 if(debug>1) err_msg("DEBUG:(%d)<=getPacketCount6( )",ret);
385 int CountRuleNumber6(char *ruleNumber)
389 if(debug>1) err_msg("DEBUG:=>countRuleNumber6(%s)", ruleNumber);
390 ret=countRuleNumber6(ruleNumber);
391 if(debug>1) err_msg("DEBUG:(%d)<=countRuleNumber6( )",ret);
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( )");