version 1.1.1.1, 2012/02/21 17:26:12
|
version 1.1.1.4, 2016/11/02 10:09:11
|
Line 27
|
Line 27
|
#include "memory.h" |
#include "memory.h" |
#include "str.h" |
#include "str.h" |
#include "log.h" |
#include "log.h" |
|
#include "jhash.h" |
|
|
#ifndef HAVE_INET_ATON |
#ifndef HAVE_INET_ATON |
int |
int |
Line 116 inet_ntop (int family, const void *addrptr, char *strp
|
Line 117 inet_ntop (int family, const void *addrptr, char *strp
|
#endif /* ! HAVE_INET_NTOP */ |
#endif /* ! HAVE_INET_NTOP */ |
|
|
const char * |
const char * |
inet_sutop (union sockunion *su, char *str) | inet_sutop (const union sockunion *su, char *str) |
{ |
{ |
switch (su->sa.sa_family) |
switch (su->sa.sa_family) |
{ |
{ |
Line 163 str2sockunion (const char *str, union sockunion *su)
|
Line 164 str2sockunion (const char *str, union sockunion *su)
|
} |
} |
|
|
const char * |
const char * |
sockunion2str (union sockunion *su, char *buf, size_t len) | sockunion2str (const union sockunion *su, char *buf, size_t len) |
{ |
{ |
if (su->sa.sa_family == AF_INET) | switch (sockunion_family(su)) |
return inet_ntop (AF_INET, &su->sin.sin_addr, buf, len); | { |
| case AF_UNSPEC: |
| snprintf (buf, len, "(unspec)"); |
| return buf; |
| case AF_INET: |
| return inet_ntop (AF_INET, &su->sin.sin_addr, buf, len); |
#ifdef HAVE_IPV6 |
#ifdef HAVE_IPV6 |
else if (su->sa.sa_family == AF_INET6) | case AF_INET6: |
return inet_ntop (AF_INET6, &su->sin6.sin6_addr, buf, len); | return inet_ntop (AF_INET6, &su->sin6.sin6_addr, buf, len); |
#endif /* HAVE_IPV6 */ |
#endif /* HAVE_IPV6 */ |
return NULL; | } |
| snprintf (buf, len, "(af %d)", sockunion_family(su)); |
| return buf; |
} |
} |
|
|
union sockunion * |
union sockunion * |
sockunion_str2su (const char *str) |
sockunion_str2su (const char *str) |
{ |
{ |
int ret; | union sockunion *su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion)); |
union sockunion *su; | |
| if (!str2sockunion (str, su)) |
su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion)); | return su; |
| |
ret = inet_pton (AF_INET, str, &su->sin.sin_addr); | |
if (ret > 0) /* Valid IPv4 address format. */ | |
{ | |
su->sin.sin_family = AF_INET; | |
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN | |
su->sin.sin_len = sizeof(struct sockaddr_in); | |
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ | |
return su; | |
} | |
#ifdef HAVE_IPV6 | |
ret = inet_pton (AF_INET6, str, &su->sin6.sin6_addr); | |
if (ret > 0) /* Valid IPv6 address format. */ | |
{ | |
su->sin6.sin6_family = AF_INET6; | |
#ifdef SIN6_LEN | |
su->sin6.sin6_len = sizeof(struct sockaddr_in6); | |
#endif /* SIN6_LEN */ | |
return su; | |
} | |
#endif /* HAVE_IPV6 */ | |
| |
XFREE (MTYPE_SOCKUNION, su); |
XFREE (MTYPE_SOCKUNION, su); |
return NULL; |
return NULL; |
} |
} |
|
|
char * |
|
sockunion_su2str (union sockunion *su) |
|
{ |
|
char str[SU_ADDRSTRLEN]; |
|
|
|
switch (su->sa.sa_family) |
|
{ |
|
case AF_INET: |
|
inet_ntop (AF_INET, &su->sin.sin_addr, str, sizeof (str)); |
|
break; |
|
#ifdef HAVE_IPV6 |
|
case AF_INET6: |
|
inet_ntop (AF_INET6, &su->sin6.sin6_addr, str, sizeof (str)); |
|
break; |
|
#endif /* HAVE_IPV6 */ |
|
} |
|
return XSTRDUP (MTYPE_TMP, str); |
|
} |
|
|
|
/* Convert IPv4 compatible IPv6 address to IPv4 address. */ |
/* Convert IPv4 compatible IPv6 address to IPv4 address. */ |
static void |
static void |
sockunion_normalise_mapped (union sockunion *su) |
sockunion_normalise_mapped (union sockunion *su) |
Line 247 sockunion_normalise_mapped (union sockunion *su)
|
Line 215 sockunion_normalise_mapped (union sockunion *su)
|
|
|
/* Return socket of sockunion. */ |
/* Return socket of sockunion. */ |
int |
int |
sockunion_socket (union sockunion *su) | sockunion_socket (const union sockunion *su) |
{ |
{ |
int sock; |
int sock; |
|
|
Line 277 sockunion_accept (int sock, union sockunion *su)
|
Line 245 sockunion_accept (int sock, union sockunion *su)
|
|
|
/* Return sizeof union sockunion. */ |
/* Return sizeof union sockunion. */ |
static int |
static int |
sockunion_sizeof (union sockunion *su) | sockunion_sizeof (const union sockunion *su) |
{ |
{ |
int ret; |
int ret; |
|
|
Line 297 sockunion_sizeof (union sockunion *su)
|
Line 265 sockunion_sizeof (union sockunion *su)
|
} |
} |
|
|
/* return sockunion structure : this function should be revised. */ |
/* return sockunion structure : this function should be revised. */ |
static char * | static const char * |
sockunion_log (union sockunion *su) | sockunion_log (const union sockunion *su, char *buf, size_t len) |
{ |
{ |
static char buf[SU_ADDRSTRLEN]; |
|
|
|
switch (su->sa.sa_family) |
switch (su->sa.sa_family) |
{ |
{ |
case AF_INET: |
case AF_INET: |
snprintf (buf, SU_ADDRSTRLEN, "%s", inet_ntoa (su->sin.sin_addr)); | return inet_ntop(AF_INET, &su->sin.sin_addr, buf, len); |
break; | |
#ifdef HAVE_IPV6 |
#ifdef HAVE_IPV6 |
case AF_INET6: |
case AF_INET6: |
snprintf (buf, SU_ADDRSTRLEN, "%s", | return inet_ntop(AF_INET6, &(su->sin6.sin6_addr), buf, len); |
inet_ntop (AF_INET6, &(su->sin6.sin6_addr), buf, SU_ADDRSTRLEN)); | |
break; |
break; |
#endif /* HAVE_IPV6 */ |
#endif /* HAVE_IPV6 */ |
|
|
default: |
default: |
snprintf (buf, SU_ADDRSTRLEN, "af_unknown %d ", su->sa.sa_family); | snprintf (buf, len, "af_unknown %d ", su->sa.sa_family); |
break; | return buf; |
} |
} |
return (XSTRDUP (MTYPE_TMP, buf)); |
|
} |
} |
|
|
/* sockunion_connect returns |
/* sockunion_connect returns |
Line 325 sockunion_log (union sockunion *su)
|
Line 290 sockunion_log (union sockunion *su)
|
0 : connect success |
0 : connect success |
1 : connect is in progress */ |
1 : connect is in progress */ |
enum connect_result |
enum connect_result |
sockunion_connect (int fd, union sockunion *peersu, unsigned short port, | sockunion_connect (int fd, const union sockunion *peersu, unsigned short port, |
unsigned int ifindex) | ifindex_t ifindex) |
{ |
{ |
int ret; |
int ret; |
int val; |
int val; |
Line 347 sockunion_connect (int fd, union sockunion *peersu, un
|
Line 312 sockunion_connect (int fd, union sockunion *peersu, un
|
{ |
{ |
#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID |
#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID |
/* su.sin6.sin6_scope_id = ifindex; */ |
/* su.sin6.sin6_scope_id = ifindex; */ |
#ifdef MUSICA |
|
su.sin6.sin6_scope_id = ifindex; |
|
#endif |
|
#endif /* HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID */ |
#endif /* HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID */ |
#ifndef MUSICA |
|
SET_IN6_LINKLOCAL_IFINDEX (su.sin6.sin6_addr, ifindex); |
SET_IN6_LINKLOCAL_IFINDEX (su.sin6.sin6_addr, ifindex); |
#endif |
|
} |
} |
#endif /* KAME */ |
#endif /* KAME */ |
break; |
break; |
Line 379 sockunion_connect (int fd, union sockunion *peersu, un
|
Line 339 sockunion_connect (int fd, union sockunion *peersu, un
|
{ |
{ |
if (errno != EINPROGRESS) |
if (errno != EINPROGRESS) |
{ |
{ |
|
char str[SU_ADDRSTRLEN]; |
zlog_info ("can't connect to %s fd %d : %s", |
zlog_info ("can't connect to %s fd %d : %s", |
sockunion_log (&su), fd, safe_strerror (errno)); | sockunion_log (&su, str, sizeof str), |
| fd, safe_strerror (errno)); |
return connect_error; |
return connect_error; |
} |
} |
} |
} |
Line 423 sockunion_bind (int sock, union sockunion *su, unsigne
|
Line 385 sockunion_bind (int sock, union sockunion *su, unsigne
|
su->sin.sin_len = size; |
su->sin.sin_len = size; |
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ |
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ |
if (su_addr == NULL) |
if (su_addr == NULL) |
su->sin.sin_addr.s_addr = htonl (INADDR_ANY); | sockunion2ip (su) = htonl (INADDR_ANY); |
} |
} |
#ifdef HAVE_IPV6 |
#ifdef HAVE_IPV6 |
else if (su->sa.sa_family == AF_INET6) |
else if (su->sa.sa_family == AF_INET6) |
Line 435 sockunion_bind (int sock, union sockunion *su, unsigne
|
Line 397 sockunion_bind (int sock, union sockunion *su, unsigne
|
#endif /* SIN6_LEN */ |
#endif /* SIN6_LEN */ |
if (su_addr == NULL) |
if (su_addr == NULL) |
{ |
{ |
#if defined(LINUX_IPV6) || defined(NRL) | #ifdef LINUX_IPV6 |
memset (&su->sin6.sin6_addr, 0, sizeof (struct in6_addr)); |
memset (&su->sin6.sin6_addr, 0, sizeof (struct in6_addr)); |
#else |
#else |
su->sin6.sin6_addr = in6addr_any; |
su->sin6.sin6_addr = in6addr_any; |
Line 567 sockopt_minttl (int family, int sock, int minttl)
|
Line 529 sockopt_minttl (int family, int sock, int minttl)
|
return -1; |
return -1; |
} |
} |
|
|
|
int |
|
sockopt_v6only (int family, int sock) |
|
{ |
|
int ret, on = 1; |
|
|
|
#ifdef HAVE_IPV6 |
|
#ifdef IPV6_V6ONLY |
|
if (family == AF_INET6) |
|
{ |
|
ret = setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, |
|
(void *) &on, sizeof (int)); |
|
if (ret < 0) |
|
{ |
|
zlog (NULL, LOG_WARNING, "can't set sockopt IPV6_V6ONLY " |
|
"to socket %d", sock); |
|
return -1; |
|
} |
|
return 0; |
|
} |
|
#endif /* IPV6_V6ONLY */ |
|
#endif /* HAVE_IPV6 */ |
|
return 0; |
|
} |
|
|
/* If same family and same prefix return 1. */ |
/* If same family and same prefix return 1. */ |
int |
int |
sockunion_same (union sockunion *su1, union sockunion *su2) | sockunion_same (const union sockunion *su1, const union sockunion *su2) |
{ |
{ |
int ret = 0; |
int ret = 0; |
|
|
Line 595 sockunion_same (union sockunion *su1, union sockunion
|
Line 581 sockunion_same (union sockunion *su1, union sockunion
|
return 0; |
return 0; |
} |
} |
|
|
|
unsigned int |
|
sockunion_hash (const union sockunion *su) |
|
{ |
|
switch (sockunion_family(su)) |
|
{ |
|
case AF_INET: |
|
return jhash_1word(su->sin.sin_addr.s_addr, 0); |
|
#ifdef HAVE_IPV6 |
|
case AF_INET6: |
|
return jhash2(su->sin6.sin6_addr.s6_addr32, ZEBRA_NUM_OF(su->sin6.sin6_addr.s6_addr32), 0); |
|
#endif /* HAVE_IPV6 */ |
|
} |
|
return 0; |
|
} |
|
|
|
size_t |
|
family2addrsize(int family) |
|
{ |
|
switch (family) |
|
{ |
|
case AF_INET: |
|
return sizeof(struct in_addr); |
|
#ifdef HAVE_IPV6 |
|
case AF_INET6: |
|
return sizeof(struct in6_addr); |
|
#endif /* HAVE_IPV6 */ |
|
} |
|
return 0; |
|
} |
|
|
|
size_t |
|
sockunion_get_addrlen(const union sockunion *su) |
|
{ |
|
return family2addrsize(sockunion_family(su)); |
|
} |
|
|
|
const u_char * |
|
sockunion_get_addr(const union sockunion *su) |
|
{ |
|
switch (sockunion_family(su)) |
|
{ |
|
case AF_INET: |
|
return (const u_char *) &su->sin.sin_addr.s_addr; |
|
#ifdef HAVE_IPV6 |
|
case AF_INET6: |
|
return (const u_char *) &su->sin6.sin6_addr; |
|
#endif /* HAVE_IPV6 */ |
|
} |
|
return NULL; |
|
} |
|
|
|
void |
|
sockunion_set(union sockunion *su, int family, const u_char *addr, size_t bytes) |
|
{ |
|
if (family2addrsize(family) != bytes) |
|
return; |
|
|
|
sockunion_family(su) = family; |
|
switch (family) |
|
{ |
|
case AF_INET: |
|
memcpy(&su->sin.sin_addr.s_addr, addr, bytes); |
|
break; |
|
#ifdef HAVE_IPV6 |
|
case AF_INET6: |
|
memcpy(&su->sin6.sin6_addr, addr, bytes); |
|
break; |
|
#endif /* HAVE_IPV6 */ |
|
} |
|
} |
|
|
/* After TCP connection is established. Get local address and port. */ |
/* After TCP connection is established. Get local address and port. */ |
union sockunion * |
union sockunion * |
sockunion_getsockname (int fd) |
sockunion_getsockname (int fd) |
Line 688 sockunion_getpeername (int fd)
|
Line 745 sockunion_getpeername (int fd)
|
|
|
/* Print sockunion structure */ |
/* Print sockunion structure */ |
static void __attribute__ ((unused)) |
static void __attribute__ ((unused)) |
sockunion_print (union sockunion *su) | sockunion_print (const union sockunion *su) |
{ |
{ |
if (su == NULL) |
if (su == NULL) |
return; |
return; |
Line 727 sockunion_print (union sockunion *su)
|
Line 784 sockunion_print (union sockunion *su)
|
|
|
#ifdef HAVE_IPV6 |
#ifdef HAVE_IPV6 |
static int |
static int |
in6addr_cmp (struct in6_addr *addr1, struct in6_addr *addr2) | in6addr_cmp (const struct in6_addr *addr1, const struct in6_addr *addr2) |
{ |
{ |
unsigned int i; |
unsigned int i; |
u_char *p1, *p2; |
u_char *p1, *p2; |
Line 747 in6addr_cmp (struct in6_addr *addr1, struct in6_addr *
|
Line 804 in6addr_cmp (struct in6_addr *addr1, struct in6_addr *
|
#endif /* HAVE_IPV6 */ |
#endif /* HAVE_IPV6 */ |
|
|
int |
int |
sockunion_cmp (union sockunion *su1, union sockunion *su2) | sockunion_cmp (const union sockunion *su1, const union sockunion *su2) |
{ |
{ |
if (su1->sa.sa_family > su2->sa.sa_family) |
if (su1->sa.sa_family > su2->sa.sa_family) |
return 1; |
return 1; |
Line 756 sockunion_cmp (union sockunion *su1, union sockunion *
|
Line 813 sockunion_cmp (union sockunion *su1, union sockunion *
|
|
|
if (su1->sa.sa_family == AF_INET) |
if (su1->sa.sa_family == AF_INET) |
{ |
{ |
if (ntohl (su1->sin.sin_addr.s_addr) == ntohl (su2->sin.sin_addr.s_addr)) | if (ntohl (sockunion2ip (su1)) == ntohl (sockunion2ip (su2))) |
return 0; |
return 0; |
if (ntohl (su1->sin.sin_addr.s_addr) > ntohl (su2->sin.sin_addr.s_addr)) | if (ntohl (sockunion2ip (su1)) > ntohl (sockunion2ip (su2))) |
return 1; |
return 1; |
else |
else |
return -1; |
return -1; |
Line 772 sockunion_cmp (union sockunion *su1, union sockunion *
|
Line 829 sockunion_cmp (union sockunion *su1, union sockunion *
|
|
|
/* Duplicate sockunion. */ |
/* Duplicate sockunion. */ |
union sockunion * |
union sockunion * |
sockunion_dup (union sockunion *su) | sockunion_dup (const union sockunion *su) |
{ |
{ |
union sockunion *dup = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion)); |
union sockunion *dup = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion)); |
memcpy (dup, su, sizeof (union sockunion)); |
memcpy (dup, su, sizeof (union sockunion)); |