static int is_ipv4_ok(main_server_st *s, struct sockaddr_storage *ip, struct sockaddr_storage *net, struct sockaddr_storage *mask) { struct sockaddr_storage broadcast; unsigned i; memcpy(&broadcast, net, sizeof(broadcast)); for (i=0;i<sizeof(struct in_addr);i++) { SA_IN_U8_P(&broadcast)[i] |= ~(SA_IN_U8_P(&mask)[i]); } if (ip_lease_exists(s, ip, sizeof(struct sockaddr_in)) != 0 || ip_cmp(ip, net) == 0 || ip_cmp(ip, &broadcast) == 0) { return 0; } return 1; }
static int is_ipv6_ok(main_server_st *s, struct sockaddr_storage *ip, struct sockaddr_storage *net, struct sockaddr_storage *mask) { if (ip_lease_exists(s, ip, sizeof(struct sockaddr_in6)) != 0 || ip_cmp(ip, net) == 0) { return 0; } return 1; }
static bool ip_lease_cmp(const void* _c1, void* _c2) { const struct ip_lease_st* c1 = _c1; struct ip_lease_st* c2 = _c2; if (c1->rip_len == c2->rip_len && ip_cmp(&c1->rip, &c2->rip, c2->rip_len) == 0) return 1; return 0; }
int handle_resume_fetch_req(main_server_st * s, struct proc_st *proc, const SessionResumeFetchMsg * req, SessionResumeReplyMsg * rep) { tls_cache_st *cache; struct htable_iter iter; size_t key; rep->reply = SESSION_RESUME_REPLY_MSG__RESUME__REP__FAILED; key = hash_any(req->session_id.data, req->session_id.len, 0); cache = htable_firstval(s->tls_db.ht, &iter, key); while (cache != NULL) { if (req->session_id.len == cache->session_id_size && memcmp(req->session_id.data, cache->session_id, req->session_id.len) == 0) { if (proc->remote_addr_len == cache->remote_addr_len && ip_cmp(&proc->remote_addr, &cache->remote_addr) == 0) { rep->reply = SESSION_RESUME_REPLY_MSG__RESUME__REP__OK; rep->has_session_data = 1; rep->session_data.data = (void *)cache->session_data; rep->session_data.len = cache->session_data_size; mslog_hex(s, proc, LOG_DEBUG, "TLS session DB resuming", req->session_id.data, req->session_id.len, 0); return 0; } } cache = htable_nextval(s->tls_db.ht, &iter, key); } return 0; }
inline int cx_track(ip_t *ip_src, uint16_t src_port,ip_t *ip_dst, uint16_t dst_port, uint8_t ip_proto, uint32_t p_bytes, uint8_t tcpflags,struct timeval tstamp, int af) { connection *cxt = NULL; connection *head = NULL; /* for non-ipv6 addresses, indexes 1, 2 and 3 are zero and don't influence the hash */ uint64_t hash = ip_hash(ip_src, ip_dst, src_port, dst_port, ip_proto, BUCKET_SIZE); cxt = bucket[hash]; head = cxt; while ( cxt != NULL ) { if ( cxt->s_port == src_port && cxt->d_port == dst_port && cxt->vlanid == vlanid && ip_cmp(cxt->s_ip, ip_src) == 0 && ip_cmp(cxt->d_ip, ip_dst) == 0 ) { cxt->s_tcpFlags |= tcpflags; cxt->s_total_bytes += p_bytes; cxt->s_total_pkts += 1; cxt->last_pkt_time = tstamp; if ( mode & MODE_DUMP ) { cxt->last_offset = dump_file_offset + p_bytes; snprintf(cxt->last_dump, STDBUF, "%s", dump_file); } else if ( mode & MODE_FILE ) { cxt->last_offset = read_file_offset + p_bytes; snprintf(cxt->last_dump, STDBUF, "%s", read_file); } return 0; } else if ( cxt->d_port == src_port && cxt->s_port == dst_port && cxt->vlanid == vlanid && ip_cmp(cxt->s_ip, ip_dst) == 0 && ip_cmp(cxt->d_ip, ip_src) == 0 ) { cxt->d_tcpFlags |= tcpflags; cxt->d_total_bytes += p_bytes; cxt->d_total_pkts += 1; cxt->last_pkt_time = tstamp; if ( mode & MODE_DUMP ) { cxt->last_offset = dump_file_offset + p_bytes; snprintf(cxt->last_dump, STDBUF, "%s", dump_file); } else if ( mode & MODE_FILE ) { cxt->last_offset = read_file_offset + p_bytes; snprintf(cxt->last_dump, STDBUF, "%s", read_file); } return 0; } cxt = cxt->next; } if ( cxt == NULL ) { cxtrackerid += 1; cxt = (connection*) calloc(1, sizeof(connection)); //cxt_alloc++; if (head != NULL ) { head->prev = cxt; } /* printf("[*] New connection...\n"); */ cxt->cxid = cxtrackerid; cxt->ipversion = af; cxt->vlanid = vlanid; cxt->s_tcpFlags = tcpflags; /* cxt->d_tcpFlags = 0x00; */ cxt->s_total_bytes = p_bytes; cxt->s_total_pkts = 1; /* cxt->d_total_bytes = 0; */ /* cxt->d_total_pkts = 0; */ cxt->start_time = tstamp; if ( mode & MODE_DUMP ) { cxt->start_offset = dump_file_offset; cxt->last_offset = cxt->start_offset + p_bytes; snprintf(cxt->start_dump, STDBUF, "%s", dump_file); snprintf(cxt->last_dump, STDBUF, "%s", dump_file); } else if ( mode & MODE_FILE ) { cxt->start_offset = read_file_offset; cxt->last_offset = cxt->start_offset + p_bytes; snprintf(cxt->start_dump, STDBUF, "%s", read_file); snprintf(cxt->last_dump, STDBUF, "%s", read_file); } else { cxt->start_offset = -1; cxt->last_offset = -1; } cxt->last_pkt_time = tstamp; cxt->s_ip = ip_src; cxt->d_ip = ip_dst; /* This should be Zeroed due to calloc */ /* if (af == AF_INET) { cxt->s_ip.s6_addr32[1] = 0; cxt->s_ip.s6_addr32[2] = 0; cxt->s_ip.s6_addr32[3] = 0; cxt->d_ip.s6_addr32[1] = 0; cxt->d_ip.s6_addr32[2] = 0; cxt->d_ip.s6_addr32[3] = 0; } */ cxt->s_port = src_port; cxt->d_port = dst_port; cxt->proto = ip_proto; cxt->next = head; //cxt->prev = NULL; /* New connections are pushed on to the head of bucket[s_hash] */ bucket[hash] = cxt; /* Return value should be 1, telling "ip_tracked" not to try * to free the memory allocated for ip_src and ip_dst */ return 1; } /* Should never be here! */ return 0; }
/* etnlegend, 2006.04.25, clean up bbsd_single ... */ #include "bbs.h" #include <arpa/telnet.h> #include <sys/resource.h> #ifdef HAVE_REVERSE_DNS #include <netdb.h> #endif /* HAVE_REVERSE_DNS */ #undef LOAD_LIMIT /* Temporarily Disable All Load Limit Detection */ #if defined(LOAD_LIMIT) && defined(AIX) #include <rpcsvc/rstat.h> #endif /* LOAD_LIMIT && AIX */ #define SOCKFD 3 /* listen sock file descriptor, should be set to 3 for consistent ! */ #define MAX_PENDING_CONNECTIONS 50 #define MAXLIST 1000 #define CON_THRESHOLD (5.0/18) /* (1000.0/3600) */ #define CON_THRESHOLD2 1.0 #ifdef HAVE_IPV6_SMTH #define KBS_SIN_MEMBER(_sin,_member) _sin.sin6_##_member #define KBS_SIN_FAMILY AF_INET6 #define KBS_SIN_ADDR_DEFAULT in6addr_any struct ip_struct { /* size on 32-bit / 64-bit machine */ struct in6_addr ip; /* 16 16 */ time_t first; /* 4 8 */ time_t last; /* 4 8 */ int t; /* 4 4 */ }; /* 28 36 bytes */ typedef struct sockaddr_in6 KBS_SOCKADDR_IN; typedef struct in6_addr KBS_IN_ADDR; #ifdef LEGACY_IPV4_DISPLAY #define KBS_SET_FROMHOST(_sin,_from) \ ( \ !ISV4ADDR(KBS_SIN_MEMBER(_sin,addr))? \ inet_ntop(AF_INET6,&KBS_SIN_MEMBER(_sin,addr),_from,IPLEN): \ inet_ntop(AF_INET,&KBS_SIN_MEMBER(_sin,addr).s6_addr[12],_from,IPLEN) \ ) #endif /* LEGACY_IPV4_DISPLAY */ #else /* ! HAVE_IPV6_SMTH */ #define KBS_SIN_MEMBER(_sin,_member) _sin.sin_##_member #define KBS_SIN_FAMILY AF_INET #define KBS_SIN_ADDR_DEFAULT inaddr_any struct ip_struct { /* size on 32-bit / 64-bit machine */ unsigned char ip[4]; /* 4 4 */ int t; /* 4 4 */ time_t first; /* 4 8 */ time_t last; /* 4 8 */ }; /* 16 24 bytes */ typedef struct sockaddr_in KBS_SOCKADDR_IN; typedef struct in_addr KBS_IN_ADDR; #endif /* HAVE_IPV6_SMTH */ #define KBS_SET_SIN_FAMILY(_sin) do{KBS_SIN_MEMBER(_sin,family)=KBS_SIN_FAMILY;}while(0) #define KBS_SET_SIN_PORT(_sin,_port) do{KBS_SIN_MEMBER(_sin,port)=htons(_port);}while(0) #define KBS_SET_SIN_ADDR(_sin,_addr) do{KBS_SIN_MEMBER(_sin,addr)=_addr;}while(0) #ifndef KBS_SET_FROMHOST #define KBS_SET_FROMHOST(_sin,_from) inet_ntop(KBS_SIN_FAMILY,&KBS_SIN_MEMBER(_sin,addr),_from,IPLEN) #endif /* KBS_SET_FROMHOST */ #ifndef SSHBBS #define KBS_WRITE(_fd,_ptr,_len) write(_fd,_ptr,_len) static const unsigned char cmd[]={ IAC,DO,TELOPT_TTYPE, /* cmd 0 size = 3 */ IAC,SB,TELOPT_TTYPE,TELQUAL_SEND,IAC,SE, /* cmd 1 size = 6 */ IAC,WILL,TELOPT_ECHO, /* cmd 2 size = 3 */ IAC,WILL,TELOPT_SGA, /* cmd 3 size = 3 */ IAC,WILL,TELOPT_BINARY, /* cmd 4 size = 3 */ IAC,DO,TELOPT_NAWS, /* cmd 5 size = 3 */ IAC,DO,TELOPT_BINARY /* cmd 6 size = 3 */ }; /* total size = 24 */ #ifndef HAVE_IPV6_SMTH static struct in_addr inaddr_any; #endif /* HAVE_IPV6_SMTH */ static int mport; static int no_fork; static int server_pid; const select_func x_select=select; const read_func x_read=read; #else /* SSHBBS */ #include "ssh_funcs.h" #define KBS_WRITE(_fd,_ptr,_len) ssh_write(_fd,_ptr,_len) extern char **saved_argv; static int ssh_exiting; const select_func x_select=ssh_select; const read_func x_read=ssh_read; #endif /* ! SSHBBS */ static const int max_load = 79; static int heavy_load; static int initIP; static struct ip_struct *ips; static struct ip_struct *bads; static struct ip_struct *proxies; static inline int proxy_getpeername(int sockfd,struct sockaddr *addr,socklen_t *len) { return getpeername(sockfd,addr,len); } static inline int local_Net_Sleep(time_t time) { fd_set fds,efds; struct timeval tv; char buf[256]; FD_ZERO(&fds);FD_ZERO(&efds); FD_SET(0,&fds);FD_SET(0,&efds); for (tv.tv_sec=time,tv.tv_usec=0;select(1,&fds,NULL,&efds,&tv)>0;tv.tv_sec=time,tv.tv_usec=0) { if (FD_ISSET(0,&efds)||!(recv(0,buf,256,0)>0)) break; FD_SET(0,&fds);FD_SET(0,&efds); } return 0; } static inline int local_prints(const char *fmt,...) { va_list ap; char buf[1024]; va_start(ap,fmt); vsprintf(buf,fmt,ap); va_end(ap); return KBS_WRITE(0,buf,strlen(buf)); } #ifdef LOAD_LIMIT static inline int get_load(double *load) { #if defined(HAVE_GETLOADAVG) return getloadavg(load,3); #elif defined(LINUX) /* ! HAVE_GETLOADAVG && LINUX */ FILE *fp; int ret; double avg[3]; load[0]=0; load[1]=0; load[2]=0; if (!(fp=fopen("/proc/loadavg","r"))) return 0; ret=fscanf(fp,"%g %g %g",&avg[0],&avg[1],&avg[2]); fclose(fp); switch (ret) { case 3: load[2]=avg[2]; case 2: load[1]=avg[1]; case 1: load[0]=avg[0]; break; default: return -1; } return ret; #else /* ! HAVE_GETLOADAVG && ! LINUX */ struct statstime rsts; rstat("localhost",&rsts); load[0]=(rs.avenrun[0]*0.00390625); /* div by 256 */ load[1]=(rs.avenrun[1]*0.00390625); load[2]=(rs.avenrun[2]*0.00390625); #endif /* HAVE_GETLOADAVG */ } #endif /* LOAD_LIMIT */ static void sig_user1(int sig) { heavy_load=1; return; } static void sig_user2(int sig) { heavy_load=0; return; } static void sig_reaper(int sig) { while (waitpid(-1,NULL,(WNOHANG|WUNTRACED))>0) continue; return; } static void sig_mainterm(int sig) { exit(0); } static int main_signals(void) { struct sigaction act; sigemptyset(&act.sa_mask); act.sa_flags=0; act.sa_flags=SA_RESTART; act.sa_handler=sig_mainterm; sigaction(SIGTERM,&act,NULL); act.sa_handler=sig_user1; sigaction(SIGUSR1,&act,NULL); act.sa_handler=sig_user2; sigaction(SIGUSR2,&act,NULL); act.sa_handler=SIG_IGN; sigaction(SIGPIPE,&act,NULL); act.sa_handler=SIG_IGN; sigaction(SIGTTOU,&act,NULL); act.sa_handler=SIG_IGN; sigaction(SIGHUP,&act,NULL); #ifndef AIX act.sa_handler=sig_reaper; act.sa_flags=SA_RESTART; #else /* AIX */ act.sa_handler=NULL; act.sa_flags=(SA_RESTART|SA_NOCLDWAIT); #endif /* ! AIX */ sigaction(SIGCHLD,&act,NULL); return 0; } #ifdef HAVE_REVERSE_DNS static void dns_query_timeout(int sig) { longjmp(byebye,sig); } static void getremotehost(char *host,size_t len) { KBS_SOCKADDR_IN sin; socklen_t sinlen; struct hostent *hp; char buf[128],*p; sinlen=sizeof(KBS_SOCKADDR_IN); proxy_getpeername(0,(struct sockaddr*)&sin,&sinlen); if (!setjmp(byebye)) { signal(SIGALRM,dns_query_timeout); alarm(5); hp=gethostbyaddr(&(KBS_SIN_MEMBER(sin,addr)),sizeof(KBS_SIN_MEMBER(sin,addr)),KBS_SIN_MEMBER(sin,family)); alarm(0); } if (hp #ifdef HAVE_IPV6_SMTH &&!strchr(hp->h_name,':') #endif /* HAVE_IPV6_SMTH */ ) snprintf(buf,128,"%s",hp->h_name); else KBS_SET_FROMHOST(sin,buf); if ((p=strstr(buf,"."NAME_BBS_ENGLISH))) *p=0; snprintf(host,len,"%s",buf); return; } #endif /* HAVE_REVERSE_DNS */ int check_IP_lists( #ifndef HAVE_IPV6_SMTH unsigned int IP2 #else /* HAVE_IPV6_SMTH */ struct in6_addr sip #endif /* ! HAVE_IPV6_SMTH */ ) { FILE *fp; char buf[1024]; int i,found,min,ret; time_t now; #ifndef HAVE_IPV6_SMTH unsigned int ip[4]; #else /* HAVE_IPV6_SMTH */ struct in6_addr rip; #endif /* ! HAVE_IPV6_SMTH */ found=0;min=0;ret=0; if (!initIP) { ips=(struct ip_struct*)malloc(MAXLIST*sizeof(struct ip_struct)); bads=(struct ip_struct*)malloc(MAXLIST*sizeof(struct ip_struct)); proxies=(struct ip_struct*)malloc(MAXLIST*sizeof(struct ip_struct)); memset(ips,0,MAXLIST*sizeof(struct ip_struct)); memset(bads,0,MAXLIST*sizeof(struct ip_struct)); memset(proxies,0,MAXLIST*sizeof(struct ip_struct)); if (!ips||!bads||!proxies) return -1; if ((fp=fopen(".denyIP","r"))) { for (i=0;fgets(buf,1024,fp);i++) { #ifndef HAVE_IPV6_SMTH if (!(sscanf(buf,"%d.%d.%d.%d",&ip[0],&ip[1],&ip[2],&ip[3])>0)) break; bads[i].ip[0]=ip[0]; bads[i].ip[1]=ip[1]; bads[i].ip[2]=ip[2]; bads[i].ip[3]=ip[3]; #else /* HAVE_IPV6_SMTH */ if (!(sscanf(buf,"%02hhX%02hhX:%02hhX%02hhX:%02hhX%02hhX:%02hhX%02hhX:" "%02hhX%02hhX:%02hhX%02hhX:%02hhX%02hhX:%02hhX%02hhX",&rip.s6_addr[0], &rip.s6_addr[1],&rip.s6_addr[2],&rip.s6_addr[3],&rip.s6_addr[4],&rip.s6_addr[5], &rip.s6_addr[6],&rip.s6_addr[7],&rip.s6_addr[8],&rip.s6_addr[9],&rip.s6_addr[10], &rip.s6_addr[11],&rip.s6_addr[12],&rip.s6_addr[13],&rip.s6_addr[14],&rip.s6_addr[15])>0)) break; ip_cpy(bads[i].ip,rip); #endif /* ! HAVE_IPV6_SMTH */ } fclose(fp); } if ((fp=fopen("etc/proxyIP","r"))) { for (i=0;fgets(buf,1024,fp);i++) { #ifndef HAVE_IPV6_SMTH if (!(sscanf(buf,"%d.%d.%d.%d",&ip[0],&ip[1],&ip[2],&ip[3])>0)) break; proxies[i].ip[0]=ip[0]; proxies[i].ip[1]=ip[1]; proxies[i].ip[2]=ip[2]; proxies[i].ip[3]=ip[3]; #else /* HAVE_IPV6_SMTH */ if (!(sscanf(buf,"%02hhX%02hhX:%02hhX%02hhX:%02hhX%02hhX:%02hhX%02hhX:" "%02hhX%02hhX:%02hhX%02hhX:%02hhX%02hhX:%02hhX%02hhX",&rip.s6_addr[0], &rip.s6_addr[1],&rip.s6_addr[2],&rip.s6_addr[3],&rip.s6_addr[4],&rip.s6_addr[5], &rip.s6_addr[6],&rip.s6_addr[7],&rip.s6_addr[8],&rip.s6_addr[9],&rip.s6_addr[10], &rip.s6_addr[11],&rip.s6_addr[12],&rip.s6_addr[13],&rip.s6_addr[14],&rip.s6_addr[15])>0)) break; ip_cpy(proxies[i].ip,rip); #endif /* ! HAVE_IPV6_SMTH */ } fclose(fp); } initIP=1; } now=time(NULL); #ifndef HAVE_IPV6_SMTH if (!(ip[0]=(IP2&0xFF))) return 0; ip[1]=((IP2>>8)&0xFF); ip[2]=((IP2>>16)&0xFF); ip[3]=((IP2>>24)&0xFF); for (i=0;i<MAXLIST;i++) { if (!(bads[i].ip[0])) break; if ((ip[0]==bads[i].ip[0])&&(ip[1]==bads[i].ip[1]) &&(ip[2]==bads[i].ip[2])&&(ip[3]==bads[i].ip[3])) return 1; } for (i=0;i<MAXLIST;i++) { if (!(proxies[i].ip[0])) break; if ((ip[0]==proxies[i].ip[0])&&(ip[1]==proxies[i].ip[1]) &&(ip[2]==proxies[i].ip[2])&&(ip[3]==proxies[i].ip[3])) return 0; } for (i=0;i<MAXLIST;i++) { if ((double)(now-ips[i].last)>3600) ips[i].ip[0]=0; if ((ip[0]==ips[i].ip[0])&&(ip[1]==ips[i].ip[1]) &&(ip[2]==ips[i].ip[2])&&(ip[3]==ips[i].ip[3])) { if (!((double)(now-ips[i].last)>CON_THRESHOLD2)) { if ((fp=fopen(".IPdenys","a"))) { fprintf(fp,"0 %ld %d.%d.%d.%d %d\n",now,ip[0],ip[1],ip[2],ip[3],ips[i].t); fclose(fp); } ret=1; } found=1; ips[i].last=now; ips[i].t++; if (!(ips[i].t<10)&&!((ips[i].t/(double)(ips[i].last-ips[i].first))<CON_THRESHOLD)) { ips[i].t=100000; if ((fp=fopen(".IPdenys","a"))) { fprintf(fp,"1 %ld %d.%d.%d.%d %d\n",now,ip[0],ip[1],ip[2],ip[3],ips[i].t); fclose(fp); } ret=1; } break; } if (ips[i].last<ips[min].last) min=i; } if (!found) { ips[min].ip[0]=ip[0]; ips[min].ip[1]=ip[1]; ips[min].ip[2]=ip[2]; ips[min].ip[3]=ip[3]; ips[min].first=now; ips[min].last=now; ips[min].t=1; } #else /* HAVE_IPV6_SMTH */ memset(&rip,0,sizeof(struct in6_addr)); for (i=0;i<MAXLIST;i++) { if (!ip_cmp(rip,bads[i].ip)) break; if (!ip_cmp(sip,bads[i].ip)) return 1; } for (i=0;i<MAXLIST;i++) { if (!ip_cmp(rip,proxies[i].ip)) break; if (!ip_cmp(sip,proxies[i].ip)) return 0; } for (i=0;i<MAXLIST;i++) { if ((double)(now-ips[i].last)>3600) memset(&ips[i].ip,0,sizeof(struct in6_addr)); if (!ip_cmp(ips[i].ip,sip)) { if (!((double)(now-ips[i].last)>CON_THRESHOLD2)) { if ((fp=fopen(".IPdenys","a"))) { fprintf(fp,"0 %ld %02hhX%02hhX:%02hhX%02hhX:%02hhX%02hhX:%02hhX%02hhX:" "%02hhX%02hhX:%02hhX%02hhX:%02hhX%02hhX:%02hhX%02hhX %d\n",now,rip.s6_addr[0], rip.s6_addr[1],rip.s6_addr[2],rip.s6_addr[3],rip.s6_addr[4],rip.s6_addr[5], rip.s6_addr[6],rip.s6_addr[7],rip.s6_addr[8],rip.s6_addr[9],rip.s6_addr[10], rip.s6_addr[11],rip.s6_addr[12],rip.s6_addr[13],rip.s6_addr[14],rip.s6_addr[15],ips[i].t); fclose(fp); } ret=1; } found=1; ips[i].last=now; ips[i].t++; if (!(ips[i].t<10)&&!((ips[i].t/(double)(ips[i].last-ips[i].first))<CON_THRESHOLD)) { ips[i].t=100000; if ((fp=fopen(".IPdenys","a"))) { fprintf(fp,"1 %ld %02hhX%02hhX:%02hhX%02hhX:%02hhX%02hhX:%02hhX%02hhX:" "%02hhX%02hhX:%02hhX%02hhX:%02hhX%02hhX:%02hhX%02hhX %d\n",now,rip.s6_addr[0], rip.s6_addr[1],rip.s6_addr[2],rip.s6_addr[3],rip.s6_addr[4],rip.s6_addr[5], rip.s6_addr[6],rip.s6_addr[7],rip.s6_addr[8],rip.s6_addr[9],rip.s6_addr[10], rip.s6_addr[11],rip.s6_addr[12],rip.s6_addr[13],rip.s6_addr[14],rip.s6_addr[15],ips[i].t); fclose(fp); } ret=1; } break; } if (ips[i].last<ips[min].last) min=i; } if (!found) { ip_cpy(ips[min].ip,rip); ips[min].first=now; ips[min].last=now; ips[min].t=1; } #endif /* ! HAVE_IPV6_SMTH */ return ret; }
static int get_ipv4_lease(main_server_st* s, struct proc_st* proc) { struct sockaddr_storage tmp, mask, network, rnd; unsigned i; unsigned max_loops = MAX_IP_TRIES; int ret; const char* c_network, *c_netmask; char buf[64]; /* Our IP accounting */ if (proc->config.ipv4_network && proc->config.ipv4_netmask) { c_network = proc->config.ipv4_network; c_netmask = proc->config.ipv4_netmask; } else { c_network = s->config->network.ipv4; c_netmask = s->config->network.ipv4_netmask; } if (c_network == NULL || c_netmask == NULL) { mslog(s, NULL, LOG_DEBUG, "there is no IPv4 network assigned"); return 0; } ret = inet_pton(AF_INET, c_network, SA_IN_P(&network)); if (ret != 1) { mslog(s, NULL, LOG_ERR, "error reading IP: %s", c_network); return -1; } ret = inet_pton(AF_INET, c_netmask, SA_IN_P(&mask)); if (ret != 1) { mslog(s, NULL, LOG_ERR, "error reading mask: %s", c_netmask); return -1; } /* mask the network (just in case it is wrong) */ for (i=0;i<sizeof(struct in_addr);i++) SA_IN_U8_P(&network)[i] &= (SA_IN_U8_P(&mask)[i]); ((struct sockaddr_in*)&network)->sin_family = AF_INET; ((struct sockaddr_in*)&network)->sin_port = 0; if (proc->config.explicit_ipv4) { /* if an explicit IP is given for that client, then * do implicit IP accounting. Require the address * to be odd, so we use the next even address as PtP. */ ret = inet_pton(AF_INET, proc->config.explicit_ipv4, SA_IN_P(&tmp)); if (ret != 1) { mslog(s, NULL, LOG_ERR, "error reading explicit IP: %s", proc->config.explicit_ipv4); return -1; } proc->ipv4 = talloc_zero(proc, struct ip_lease_st); if (proc->ipv4 == NULL) return ERR_MEM; ((struct sockaddr_in*)&tmp)->sin_family = AF_INET; ((struct sockaddr_in*)&tmp)->sin_port = 0; memcpy(&proc->ipv4->rip, &tmp, sizeof(struct sockaddr_in)); proc->ipv4->rip_len = sizeof(struct sockaddr_in); if (is_ipv4_ok(s, &proc->ipv4->rip, &network, &mask) == 0) { mslog(s, proc, LOG_DEBUG, "cannot assign explicit IP %s; it is in use or invalid", human_addr((void*)&tmp, sizeof(struct sockaddr_in), buf, sizeof(buf))); ret = ERR_NO_IP; goto fail; } /* LIP = network address + 1 */ memcpy(&proc->ipv4->lip, &network, sizeof(struct sockaddr_in)); proc->ipv4->lip_len = sizeof(struct sockaddr_in); SA_IN_U8_P(&proc->ipv4->lip)[3] |= 1; if (ip_cmp(&proc->ipv4->lip, &proc->ipv4->rip) == 0) { mslog(s, NULL, LOG_ERR, "cannot assign explicit IP %s; network: %s", proc->config.explicit_ipv4, c_network); ret = ERR_NO_IP; goto fail; } return 0; }