From 4ee70e3eacbd1f0dbf24ea3d5a2048422af3c6c1 Mon Sep 17 00:00:00 2001 From: Nick Peng Date: Fri, 8 Jun 2018 00:56:32 +0800 Subject: [PATCH] Update code --- conf.c | 57 ++-------- conf.h | 6 + dns.c | 2 +- dns_client.c | 21 ++-- dns_server.c | 22 ++-- fast_ping.c | 8 +- fast_ping.h | 2 +- smartdns.c | 300 ++++++++++++++++---------------------------------- smartdns.conf | 9 +- util.c | 54 ++++++++- util.h | 5 + 11 files changed, 204 insertions(+), 282 deletions(-) diff --git a/conf.c b/conf.c index d7e8b3f..229bdfd 100644 --- a/conf.c +++ b/conf.c @@ -1,5 +1,6 @@ #include "conf.h" #include "tlog.h" +#include "util.h" #include #include #include @@ -8,7 +9,6 @@ #define MAX_LINE_LEN 1024 #define MAX_KEY_LEN 64 -#define DEFAULT_DNS_PORT 53 #define DEFAULT_DNS_CACHE_SIZE 512 int dns_conf_port = DEFAULT_DNS_PORT; @@ -28,67 +28,28 @@ int config_port(char *value) return 0; } -int config_parse_ip(char *value, char *ip, unsigned short *port) -{ - int offset = 0; - char *colon = NULL; - - if (strstr(value, "[")) { - /* ipv6 with port */ - char *bracket_end = strstr(value, "]"); - if (bracket_end == NULL) { - return -1; - } - - offset = bracket_end - value - 1; - memcpy(ip, value + 1, offset); - ip[offset] = 0; - - colon = bracket_end + 1; - - } else if (strstr(value, "::")) { - /* ipv6 without port */ - strncpy(ip, value, DNS_MAX_IPLEN); - colon = NULL; - } else { - /* ipv4 */ - colon = strstr(value, ":"); - if (colon == NULL) { - /* without port */ - strncpy(ip, value, DNS_MAX_IPLEN); - } else { - /* with port */ - offset = colon - value; - colon++; - memcpy(ip, value, offset); - } - } - - if (colon) { - /* get port num */ - *port = atoi(colon); - } else { - *port = DEFAULT_DNS_PORT; - } - - return 0; -} - int config_server(char *value, dns_conf_server_type_t type) { int index = dns_conf_server_num; struct dns_servers *server; + int port = -1; + if (index >= DNS_MAX_SERVERS) { tlog(TLOG_ERROR, "exceeds max server number"); return -1; } server = &dns_conf_servers[index]; - if (config_parse_ip(value, server->server, &server->port) != 0) { + if (parse_ip(value, server->server, &port) != 0) { return -1; } + if (port == PORT_NOT_DEFINED) { + port= DEFAULT_DNS_PORT; + } + server->type = type; + server->port = port; dns_conf_server_num++; return 0; diff --git a/conf.h b/conf.h index f1e2b18..d8c6a86 100644 --- a/conf.h +++ b/conf.h @@ -2,6 +2,8 @@ #define DNS_MAX_SERVERS 32 #define DNS_MAX_IPLEN 64 +#define DNS_MAX_PATH 1024 +#define DEFAULT_DNS_PORT 53 typedef enum dns_conf_server_type { DNS_CONF_TYPE_UDP, @@ -19,6 +21,10 @@ extern int dns_conf_port; extern int dns_conf_cachesize; extern struct dns_servers dns_conf_servers[DNS_MAX_SERVERS]; extern int dns_conf_server_num; +extern int dns_conf_verbose; +extern int dns_conf_loglevel; +extern char dns_conf_logfile[DNS_MAX_PATH]; +extern int dns_conf_lognum; int load_conf(const char *file); diff --git a/dns.c b/dns.c index d1d4304..d21c678 100644 --- a/dns.c +++ b/dns.c @@ -1045,7 +1045,7 @@ static int _dns_decode_an(struct dns_context *context, dns_rr_type type) } break; default: context->ptr += rr_len; - tlog(TLOG_DEBUG, "type = %d", qtype); + tlog(TLOG_DEBUG, "DNS type = %d not supported", qtype); break; } diff --git a/dns_client.c b/dns_client.c index 12730ea..09b06e1 100644 --- a/dns_client.c +++ b/dns_client.c @@ -175,9 +175,9 @@ int _dns_client_server_add(char *server_ip, struct addrinfo *gai, dns_server_typ } memcpy(&server_info->addr, gai->ai_addr, gai->ai_addrlen); - // if (fast_ping_start(server_ip, 0, 60000, NULL, server_info) == NULL) { - // goto errout; - // } + if (fast_ping_start(server_ip, 0, 60000, 1000, NULL, server_info) == NULL) { + goto errout; + } pthread_mutex_lock(&client.server_list_lock); list_add(&server_info->list, &client.dns_server_list); @@ -206,9 +206,9 @@ int _dns_client_server_remove(char *server_ip, struct addrinfo *gai, dns_server_ } list_del(&server_info->list); pthread_mutex_unlock(&client.server_list_lock); - // if (fast_ping_stop(server_info->ping_host) != 0) { - // tlog(TLOG_ERROR, "stop ping failed.\n"); - // } + if (fast_ping_stop(server_info->ping_host) != 0) { + tlog(TLOG_ERROR, "stop ping failed.\n"); + } free(server_info); return 0; } @@ -478,7 +478,6 @@ static int _dns_client_send_udp(struct dns_server_info *server_info, void *packe int send_len = 0; send_len = sendto(client.udp, packet, len, 0, (struct sockaddr *)&server_info->addr, server_info->addr_len); if (send_len != len) { - tlog(TLOG_ERROR, "send to server failed."); return -1; } @@ -505,6 +504,8 @@ static int _dns_client_send_packet(struct dns_query_struct *query, void *packet, } if (ret != 0) { + char server_addr[128]; + tlog(TLOG_ERROR, "send query to %s failed, %s", gethost_by_addr(server_addr, &server_info->addr, server_info->addr_len), strerror(errno)); atomic_dec(&query->dns_request_sent); continue; } @@ -694,8 +695,8 @@ void dns_debug(void) } fd = open("dns-cmp.bin", O_CREAT | O_TRUNC | O_RDWR); - write(fd, data, len); - close(fd); + write(fd, data, len); + close(fd); } int dns_client_init() @@ -703,7 +704,7 @@ int dns_client_init() pthread_attr_t attr; int epollfd = -1; int ret; - int fd = 1; + int fd = -1; if (client.epoll_fd > 0) { return -1; diff --git a/dns_server.c b/dns_server.c index aacfeae..665537a 100644 --- a/dns_server.c +++ b/dns_server.c @@ -18,6 +18,7 @@ #include "dns_server.h" #include "atomic.h" +#include "conf.h" #include "dns.h" #include "dns_client.h" #include "fast_ping.h" @@ -25,7 +26,6 @@ #include "list.h" #include "tlog.h" #include "util.h" -#include "conf.h" #include #include #include @@ -282,7 +282,8 @@ void _dns_server_request_release(struct dns_request *request) } _dns_server_request_complete(request); - hash_for_each_safe(request->ip_map, bucket, tmp, addr_map, node) { + hash_for_each_safe(request->ip_map, bucket, tmp, addr_map, node) + { hash_del(&addr_map->node); free(addr_map); } @@ -399,7 +400,7 @@ int _dns_ip_address_check_add(struct dns_request *request, unsigned char *addr, return 0; } -static int _dns_client_process_answer(struct dns_request *request, char *domain, struct dns_packet *packet) +static int _dns_server_process_answer(struct dns_request *request, char *domain, struct dns_packet *packet) { int ttl; char name[DNS_MAX_CNAME_LEN] = {0}; @@ -435,11 +436,11 @@ static int _dns_client_process_answer(struct dns_request *request, char *domain, _dns_server_request_release(request); break; } - tlog(TLOG_INFO, "%s %d : %d.%d.%d.%d", name, ttl, addr[0], addr[1], addr[2], addr[3]); + tlog(TLOG_DEBUG, "domain: %s TTL:%d IP: %d.%d.%d.%d", name, ttl, addr[0], addr[1], addr[2], addr[3]); sprintf(ip, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); if (strncmp(name, domain, DNS_MAX_CNAME_LEN) == 0 || strncmp(request->alias, name, DNS_MAX_CNAME_LEN) == 0) { - if (fast_ping_start(ip, 1, 1000, _dns_server_ping_result, request) == NULL) { + if (fast_ping_start(ip, 1, 0, 1000, _dns_server_ping_result, request) == NULL) { _dns_server_request_release(request); } } @@ -459,16 +460,19 @@ static int _dns_client_process_answer(struct dns_request *request, char *domain, break; } + tlog(TLOG_DEBUG, "domain: %s TTL: %d IP: %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x", name, ttl, addr[0], addr[1], addr[2], addr[3], addr[4], + addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]); + sprintf(name, "%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]); - if (fast_ping_start(name, 1, 1000, _dns_server_ping_result, request) == NULL) { + if (fast_ping_start(name, 1, 0, 1000, _dns_server_ping_result, request) == NULL) { _dns_server_request_release(request); } } break; case DNS_T_NS: { char cname[128]; dns_get_CNAME(rrs, name, 128, &ttl, cname, 128); - tlog(TLOG_INFO, "NS: %s %d : %s\n", name, ttl, cname); + tlog(TLOG_DEBUG, "NS: %s %d : %s\n", name, ttl, cname); } break; case DNS_T_CNAME: { char cname[128]; @@ -507,7 +511,7 @@ static int dns_server_resolve_callback(char *domain, dns_result_type rtype, stru _dns_reply_inpacket(request, inpacket, inpacket_len); return -1; } - _dns_client_process_answer(request, domain, packet); + _dns_server_process_answer(request, domain, packet); return 0; } else if (rtype == DNS_QUERY_ERR) { tlog(TLOG_ERROR, "request faield, %s", domain); @@ -616,7 +620,7 @@ static int _dns_server_recv(unsigned char *inpacket, int inpacket_len, struct so memset(request, 0, sizeof(*request)); request->ttl_v4 = -1; request->ttl_v6 = -1; - request->rcode = -1; + request->rcode = DNS_RC_SERVFAIL; if (request == NULL) { tlog(TLOG_ERROR, "malloc failed.\n"); goto errout; diff --git a/fast_ping.c b/fast_ping.c index 1c93ea2..b494ff2 100755 --- a/fast_ping.c +++ b/fast_ping.c @@ -298,8 +298,11 @@ static int _fast_ping_sendping_v6(struct ping_host_struct *ping_host) len = sendto(ping_host->fd, &ping_host->packet, sizeof(struct fast_ping_packet), 0, (struct sockaddr *)&ping_host->addr, ping_host->addr_len); if (len < 0 || len != sizeof(struct fast_ping_packet)) { + if (errno == ENETUNREACH) { + goto errout; + } char ping_host_name[PING_MAX_HOSTLEN]; - tlog(TLOG_ERROR, "sendto %s %s\n", gethost_by_addr(ping_host_name, (struct sockaddr *)&ping_host->addr, ping_host->addr_len), strerror(errno)); + tlog(TLOG_ERROR, "sendto %s %s", gethost_by_addr(ping_host_name, (struct sockaddr *)&ping_host->addr, ping_host->addr_len), strerror(errno)); goto errout; } @@ -459,7 +462,7 @@ void fast_ping_print_result(struct ping_host_struct *ping_host, const char *host } } -struct ping_host_struct *fast_ping_start(const char *host, int count, int timeout, fast_ping_result ping_callback, void *userptr) +struct ping_host_struct *fast_ping_start(const char *host, int count, int interval, int timeout, fast_ping_result ping_callback, void *userptr) { struct ping_host_struct *ping_host = NULL; struct addrinfo *gai = NULL; @@ -504,7 +507,6 @@ struct ping_host_struct *fast_ping_start(const char *host, int count, int timeou goto errout; } - int interval = 1000; memset(ping_host, 0, sizeof(*ping_host)); strncpy(ping_host->host, host, PING_MAX_HOSTLEN); ping_host->fd = fd; diff --git a/fast_ping.h b/fast_ping.h index 91d8636..cbc56fa 100755 --- a/fast_ping.h +++ b/fast_ping.h @@ -23,7 +23,7 @@ typedef enum { struct ping_host_struct; typedef void (*fast_ping_result)(struct ping_host_struct *ping_host, const char *host, FAST_PING_RESULT result, struct sockaddr *addr, socklen_t addr_len, int seqno, struct timeval *tv, void *userptr); -struct ping_host_struct *fast_ping_start(const char *host, int count, int timeout, fast_ping_result ping_callback, void *userptr); +struct ping_host_struct *fast_ping_start(const char *host, int count, int interval, int timeout, fast_ping_result ping_callback, void *userptr); int fast_ping_stop(struct ping_host_struct *ping_host); diff --git a/smartdns.c b/smartdns.c index 7c174ba..0b438f8 100755 --- a/smartdns.c +++ b/smartdns.c @@ -1,7 +1,7 @@ /************************************************************************* -* -* Copyright (C) 2018 Ruilin Peng (Nick) . -* + * + * Copyright (C) 2018 Ruilin Peng (Nick) . + * * smartdns is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -16,31 +16,74 @@ * along with this program. If not, see . */ -#include "fast_ping.h" +#include "atomic.h" +#include "conf.h" #include "dns_client.h" #include "dns_server.h" +#include "fast_ping.h" #include "hashtable.h" #include "list.h" #include "tlog.h" -#include "conf.h" -#include "atomic.h" +#include "util.h" +#include +#include #include #include +#include -atomic_t r = ATOMIC_INIT(0); +#define RESOLVE_FILE "/etc/resolv.conf" +#define MAX_LINE_LEN 1024 +#define MAX_KEY_LEN 64 -void print_result(struct ping_host_struct *ping_host, const char *host, FAST_PING_RESULT result, struct sockaddr *addr, socklen_t addr_len, int seqno, - struct timeval *tv, void *userptr) +int smartdns_load_from_resolv(void) { - atomic_inc(&r); - #if 0 - if (result == PING_RESULT_RESPONSE) { - double rtt = tv->tv_sec * 1000.0 + tv->tv_usec / 1000.0; - printf("from %15s: seq=%d time=%.3f\n", host, seqno, rtt); - } else if (result == PING_RESULT_TIMEOUT) { - printf("from %15s: seq=%d timeout\n", host, seqno); + FILE *fp = NULL; + char line[MAX_LINE_LEN]; + char key[MAX_KEY_LEN]; + char value[MAX_LINE_LEN]; + char ns_ip[DNS_MAX_IPLEN]; + int port = PORT_NOT_DEFINED; + int ret = -1; + + int filed_num = 0; + int line_num = 0; + + fp = fopen(RESOLVE_FILE, "r"); + if (fp == NULL) { + tlog(TLOG_ERROR, "open %s failed, %s", RESOLVE_FILE, strerror(errno)); + return -1; } - #endif + + while (fgets(line, MAX_LINE_LEN, fp)) { + line_num++; + filed_num = sscanf(line, "%63s %1023[^\r\n]s", key, value); + + if (filed_num != 2) { + continue; + } + + if (strncmp(key, "nameserver", MAX_KEY_LEN) != 0) { + continue; + } + + if (parse_ip(value, ns_ip, &port) != 0) { + continue; + } + + if (port == PORT_NOT_DEFINED) { + port = DEFAULT_DNS_PORT; + } + + strncpy(dns_conf_servers[dns_conf_server_num].server, ns_ip, DNS_MAX_IPLEN); + dns_conf_servers[dns_conf_server_num].port = port; + dns_conf_servers[dns_conf_server_num].type = DNS_SERVER_UDP; + dns_conf_server_num++; + ret = 0; + } + + fclose(fp); + + return ret; } int smartdns_add_servers(void) @@ -53,227 +96,78 @@ int smartdns_add_servers(void) tlog(TLOG_ERROR, "add server failed, %s:%d", dns_conf_servers[i].server, dns_conf_servers[i].port); return -1; } - } + } return 0; } int smartdns_init() { - int ret; + int ret; if (load_conf("smartdns.conf") != 0) { fprintf(stderr, "load config failed."); - goto errout; } ret = tlog_init(".", "smartdns.log", 1024 * 1024, 8, 1, 0, 0); - if (ret != 0) { + if (ret != 0) { tlog(TLOG_ERROR, "start tlog failed.\n"); goto errout; } tlog_setlogscreen(1); - //tlog_setlevel(TLOG_ERROR); + tlog_setlevel(TLOG_DEBUG); + + if (dns_conf_server_num <= 0) { + if (smartdns_load_from_resolv() != 0) { + tlog(TLOG_ERROR, "load dns from resolv failed."); + goto errout; + } + } ret = fast_ping_init(); - if (ret != 0) { - tlog(TLOG_ERROR, "start ping failed.\n"); - goto errout; - } + if (ret != 0) { + tlog(TLOG_ERROR, "start ping failed.\n"); + goto errout; + } - ret = dns_server_init(); - if (ret != 0) { - tlog(TLOG_ERROR, "start dns server failed.\n"); - goto errout; - } + ret = dns_server_init(); + if (ret != 0) { + tlog(TLOG_ERROR, "start dns server failed.\n"); + goto errout; + } - ret = dns_client_init(); - if (ret != 0) { - tlog(TLOG_ERROR, "start dns client failed.\n"); - goto errout; - } + ret = dns_client_init(); + if (ret != 0) { + tlog(TLOG_ERROR, "start dns client failed.\n"); + goto errout; + } ret = smartdns_add_servers(); - if (ret != 0) { + if (ret != 0) { tlog(TLOG_ERROR, "add servers failed."); goto errout; } - /* - dns_add_server("192.168.1.1", 53, DNS_SERVER_UDP); - dns_add_server("114.114.114.114", 53, DNS_SERVER_UDP); - dns_add_server("123.207.137.88", 53, DNS_SERVER_UDP); - dns_add_server("193.112.15.186", 53, DNS_SERVER_UDP); - dns_add_server("202.141.178.13", 5353, DNS_SERVER_UDP); - dns_add_server("208.67.222.222", 5353, DNS_SERVER_UDP); - dns_add_server("77.88.8.8", 53, DNS_SERVER_UDP); - dns_add_server("202.141.162.123", 53, DNS_SERVER_UDP); - dns_add_server("101.132.183.99", 53, DNS_SERVER_UDP); - */ - // int i = 0; - // for(i = 0; i < 10; i++) - // { - // fast_ping_start("205.185.208.142", 1, 1000, print_result, NULL); - // fast_ping_start("205.185.208.142", 1, 1000, print_result, NULL); - // fast_ping_start("205.185.208.142", 1, 1000, print_result, NULL); - // fast_ping_start("205.185.208.142", 1, 1000, print_result, NULL); - // fast_ping_start("192.168.1.1", 1, 1000, print_result, NULL); - // fast_ping_start("192.168.1.1", 1, 1000, print_result, NULL); - // fast_ping_start("192.168.1.1", 1, 1000, print_result, NULL); - // fast_ping_start("192.168.1.1", 1, 1000, print_result, NULL); - // fast_ping_start("123.207.137.88", 1, 1000, print_result, NULL); - // fast_ping_start("123.207.137.88", 1, 1000, print_result, NULL); - // fast_ping_start("123.207.137.88", 1, 1000, print_result, NULL); - // fast_ping_start("123.207.137.88", 1, 1000, print_result, NULL); - // } - - // sleep(2); - // printf("i = %d, n = %d\n", i, atomic_read(&r)); - return 0; errout: - return -1; + return -1; } int smartdns_run() { - return dns_server_run(); + return dns_server_run(); } void smartdns_exit() { - fast_ping_exit(); - dns_client_exit(); - dns_server_exit(); + fast_ping_exit(); + dns_client_exit(); + dns_server_exit(); tlog_exit(); } -struct data { - struct list_head list; - int n; -}; - -void list_test() -{ - struct list_head head; - struct list_head *iter; - int i = 0; - - INIT_LIST_HEAD(&head); - - for (i = 0; i < 10; i++) { - struct data *h = malloc(sizeof(struct data)); - h->n = i; - list_add(&h->list, &head); - } - - list_for_each(iter, &head) - { - struct data *d = list_entry(iter, struct data, list); - printf("%d\n", d->n); - } -} - -struct data_hash { - struct hlist_node node; - int n; - char str[32]; -}; - -int hash_test() -{ - DEFINE_HASHTABLE(ht, 7); - struct data_hash *temp; - struct data_hash *obj; - int i; - int key; - - for (i = 11; i < 17; i++) { - temp = malloc(sizeof(struct data_hash)); - temp->n = i * i; - hash_add(ht, &temp->node, temp->n); - } - - for (i = 11; i < 17; i++) { - key = i * i; - hash_for_each_possible(ht, obj, node, key) - { - printf("value: %d\n", obj->n); - }; - } - - return 0; -} - -int hash_string_test() -{ - DEFINE_HASHTABLE(ht, 7); - struct data_hash *temp; - struct data_hash *obj; - int i; - int key; - - for (i = 0; i < 10; i++) { - temp = malloc(sizeof(struct data_hash)); - sprintf(temp->str, "%d", i); - hash_add(ht, &temp->node, hash_string(temp->str)); - } - - for (i = 0; i < 10; i++) { - char key_str[32]; - sprintf(key_str, "%d", i); - key = hash_string(key_str); - hash_for_each_possible(ht, obj, node, key) - { - printf("i = %d value: %s\n", i, obj->str); - }; - } - - return 0; -} - -#if 0 -struct data_rbtree { - struct rb_node list; - int value; -}; - -int rbtree_test() -{ - struct rb_root root; - struct rb_node *n; - RB_EMPTY_ROOT(&root); - int i; - - for (i = 0; i < 10; i++) - { - struct data_rbtree *r = malloc(sizeof(struct data_rbtree)); - r->value = i; - rb_insert(&r->list, &root); - } - - n = rb_first(&root); - int num = 5; - while (n) { - struct data_rbtree *r = container_of(n, struct data_rbtree, list); - if (r->value < num) { - n = n->rb_left; - } else if (r->value > num) { - n = n->rb_right; - } else { - printf("n = %d\n", r->value); - break; - } - } - - return 0; -} -#endif - -#include - void sig_handle(int sig) { tlog(TLOG_ERROR, "process exit.\n"); @@ -282,18 +176,18 @@ void sig_handle(int sig) int main(int argc, char *argv[]) { - int ret; + int ret; atexit(smartdns_exit); signal(SIGABRT, sig_handle); ret = smartdns_init(); - if (ret != 0) { - goto errout; - } + if (ret != 0) { + goto errout; + } - return smartdns_run(); + return smartdns_run(); errout: - return 1; + return 1; } \ No newline at end of file diff --git a/smartdns.conf b/smartdns.conf index 9bcbf7b..f6dda80 100644 --- a/smartdns.conf +++ b/smartdns.conf @@ -3,11 +3,14 @@ port 53 cache-size 1024 +loglevel info server 114.114.114.114 server 123.207.137.88 -server 202.141.178.13:5353 +server 119.29.29.29 +server 223.5.5.5 server 208.67.222.222:5353 -server 77.88.8.8:53 +server 202.141.178.13:5353 +#server 77.88.8.8:53 server 202.141.162.123:53 -server 101.132.183.99:53 +server 101.132.183.99:53 \ No newline at end of file diff --git a/util.c b/util.c index b6feea7..2c579e7 100644 --- a/util.c +++ b/util.c @@ -1,17 +1,17 @@ #include "util.h" -#include #include #include #include #include +#include unsigned long get_tick_count() { - struct timespec ts; + struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); + clock_gettime(CLOCK_MONOTONIC, &ts); - return (ts.tv_sec * 1000 + ts.tv_nsec / 1000000); + return (ts.tv_sec * 1000 + ts.tv_nsec / 1000000); } char *gethost_by_addr(char *host, struct sockaddr *addr, socklen_t addr_len) @@ -42,4 +42,50 @@ char *gethost_by_addr(char *host, struct sockaddr *addr, socklen_t addr_len) return host; errout: return NULL; +} + +int parse_ip(char *value, char *ip, int *port) +{ + int offset = 0; + char *colon = NULL; + + if (strstr(value, "[")) { + /* ipv6 with port */ + char *bracket_end = strstr(value, "]"); + if (bracket_end == NULL) { + return -1; + } + + offset = bracket_end - value - 1; + memcpy(ip, value + 1, offset); + ip[offset] = 0; + + colon = bracket_end + 1; + + } else if (strstr(value, "::")) { + /* ipv6 without port */ + strncpy(ip, value, MAX_IP_LEN); + colon = NULL; + } else { + /* ipv4 */ + colon = strstr(value, ":"); + if (colon == NULL) { + /* without port */ + strncpy(ip, value, MAX_IP_LEN); + } else { + /* with port */ + offset = colon - value; + colon++; + memcpy(ip, value, offset); + } + } + + if (colon) { + /* get port num */ + *port = atoi(colon); + } else { + *port = PORT_NOT_DEFINED; + } + + return 0; } \ No newline at end of file diff --git a/util.h b/util.h index 737be34..f37578a 100644 --- a/util.h +++ b/util.h @@ -5,8 +5,13 @@ #include +#define PORT_NOT_DEFINED -1 +#define MAX_IP_LEN 64 + unsigned long get_tick_count(); char *gethost_by_addr(char *host, struct sockaddr *addr, socklen_t addr_len); +int parse_ip(char *value, char *ip, int *port); + #endif \ No newline at end of file