int ip_cmp(const struct sockaddr_storage *s1, const struct sockaddr_storage *s2) { if (((struct sockaddr*)s1)->sa_family == AF_INET) { return memcmp(SA_IN_P(s1), SA_IN_P(s2), sizeof(struct in_addr)); } else { /* inet6 */ return memcmp(SA_IN6_P(s1), SA_IN6_P(s2), sizeof(struct in6_addr)); } }
/* Test the IP banning functionality */ static unsigned check_if_banned_str(main_server_st *s, const char *ip) { struct sockaddr_storage addr; int ret; if (strchr(ip, ':') != 0) { ret = inet_pton(AF_INET6, ip, SA_IN6_P(&addr)); addr.ss_family = AF_INET6; } else { ret = inet_pton(AF_INET, ip, SA_IN_P(&addr)); addr.ss_family = AF_INET; } if (ret != 1) { fprintf(stderr, "cannot convert IP: %s\n", ip); exit(1); } return check_if_banned(s, &addr, addr.ss_family==AF_INET?sizeof(struct sockaddr_in):sizeof(struct sockaddr_in6)); }
static void add_utmp_entry(main_server_st *s, struct proc_st* proc) { #ifdef HAVE_LIBUTIL struct utmpx entry; struct timespec tv; if (s->config->use_utmp == 0) return; memset(&entry, 0, sizeof(entry)); entry.ut_type = USER_PROCESS; entry.ut_pid = proc->pid; snprintf(entry.ut_line, sizeof(entry.ut_line), "%s", proc->tun_lease.name); snprintf(entry.ut_user, sizeof(entry.ut_user), "%s", proc->username); #ifdef __linux__ if (proc->remote_addr_len == sizeof(struct sockaddr_in)) memcpy(entry.ut_addr_v6, SA_IN_P(&proc->remote_addr), sizeof(struct in_addr)); else memcpy(entry.ut_addr_v6, SA_IN6_P(&proc->remote_addr), sizeof(struct in6_addr)); #endif gettime(&tv); entry.ut_tv.tv_sec = tv.tv_sec; entry.ut_tv.tv_usec = tv.tv_nsec / 1000; getnameinfo((void*)&proc->remote_addr, proc->remote_addr_len, entry.ut_host, sizeof(entry.ut_host), NULL, 0, NI_NUMERICHOST); setutxent(); pututxline(&entry); endutxent(); #if defined(WTMPX_FILE) updwtmpx(WTMPX_FILE, &entry); #endif return; #endif }
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]; 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 && c_netmask) { 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; } proc->ipv4 = calloc(1, sizeof(*proc->ipv4)); if (proc->ipv4 == NULL) return ERR_MEM; /* 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; memcpy(&tmp, &network, sizeof(tmp)); ((struct sockaddr_in*)&tmp)->sin_family = AF_INET; ((struct sockaddr_in*)&tmp)->sin_port = 0; memset(&rnd, 0, sizeof(rnd)); ((struct sockaddr_in*)&rnd)->sin_family = AF_INET; ((struct sockaddr_in*)&rnd)->sin_port = 0; do { if (max_loops == 0) { mslog(s, proc, LOG_ERR, "could not figure out a valid IPv4 IP."); ret = ERR_NO_IP; goto fail; } if (max_loops == MAX_IP_TRIES) { uint32_t t = hash_any(proc->username, strlen(proc->username), 0); memcpy(SA_IN_U8_P(&rnd), &t, 4); } else gnutls_rnd(GNUTLS_RND_NONCE, SA_IN_U8_P(&rnd), sizeof(struct in_addr)); max_loops--; if (SA_IN_U8_P(&rnd)[3] == 255) /* broadcast */ bignum_add(SA_IN_U8_P(&rnd), sizeof(struct in_addr), 1); /* Mask the random number with the netmask */ for (i=0;i<sizeof(struct in_addr);i++) { SA_IN_U8_P(&rnd)[i] &= ~(SA_IN_U8_P(&mask)[i]); } SA_IN_U8_P(&rnd)[sizeof(struct in_addr)-1] &= 0xFE; /* Now add the IP to the masked random number */ for (i=0;i<sizeof(struct in_addr);i++) SA_IN_U8_P(&rnd)[i] |= (SA_IN_U8_P(&network)[i]); /* check if it exists in the hash table */ if (ip_lease_exists(s, &rnd, sizeof(struct sockaddr_in)) != 0) { mslog(s, proc, LOG_DEBUG, "cannot assign remote IP %s to '%s'; it is in use.", human_addr((void*)&rnd, sizeof(struct sockaddr_in), buf, sizeof(buf)), proc->username); continue; } memcpy(&proc->ipv4->lip, &rnd, sizeof(struct sockaddr_in)); proc->ipv4->lip_len = sizeof(struct sockaddr_in); /* RIP = LIP + 1 */ memcpy(&tmp, &proc->ipv4->lip, sizeof(struct sockaddr_in)); bignum_add(SA_IN_U8_P(&tmp), sizeof(struct in_addr), 1); /* check if it exists in the hash table */ if (ip_lease_exists(s, &tmp, sizeof(struct sockaddr_in)) != 0) { mslog(s, proc, LOG_DEBUG, "cannot assign remote IP %s to '%s'; it is in use.", human_addr((void*)&tmp, sizeof(struct sockaddr_in), buf, sizeof(buf)), proc->username); continue; } memcpy(&proc->ipv4->rip, &tmp, sizeof(struct sockaddr_in)); proc->ipv4->rip_len = sizeof(struct sockaddr_in); /* mask the last IP with the netmask */ for (i=0;i<sizeof(struct in_addr);i++) SA_IN_U8_P(&tmp)[i] &= (SA_IN_U8_P(&mask)[i]); /* the result should match the network */ if (memcmp(SA_IN_U8_P(&network), SA_IN_U8_P(&tmp), sizeof(struct in_addr)) != 0) { continue; } mslog(s, proc, LOG_DEBUG, "selected IP for '%s': %s", proc->username, human_addr((void*)&proc->ipv4->lip, proc->ipv4->lip_len, buf, sizeof(buf))); if (icmp_ping4(s, (void*)&proc->ipv4->lip, (void*)&proc->ipv4->rip) == 0) break; } while(1); } return 0; fail: free(proc->ipv4); proc->ipv4 = NULL; 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; }