Commit 9631d32f authored by dermiste's avatar dermiste

adding IPv4 support in kernel_socket.c

parent a9ed7f3d
...@@ -206,7 +206,7 @@ kernel_setup_socket(int setup) ...@@ -206,7 +206,7 @@ kernel_setup_socket(int setup)
int zero = 0; int zero = 0;
if(setup) { if(setup) {
if(kernel_socket < 0) { if(kernel_socket < 0) {
kernel_socket = socket(PF_ROUTE, SOCK_RAW, AF_INET6); kernel_socket = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
if(kernel_socket < 0) if(kernel_socket < 0)
return -1; return -1;
} }
...@@ -318,9 +318,13 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen, ...@@ -318,9 +318,13 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
unsigned char msg[512]; unsigned char msg[512];
struct rt_msghdr *rtm; struct rt_msghdr *rtm;
struct sockaddr_in6 *sin6; struct sockaddr_in6 *sin6;
int rc, len; struct sockaddr_in *sin4;
int rc, len, ipv4;
char local[1][1][16] = IN6ADDR_LOOPBACK_INIT; char local6[1][1][16] = IN6ADDR_LOOPBACK_INIT;
char local4[1][1][16] =
{{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x01 }}};
/* Check that the protocol family is consistent. */ /* Check that the protocol family is consistent. */
if(plen >= 96 && v4mapped(dest)) { if(plen >= 96 && v4mapped(dest)) {
...@@ -328,17 +332,13 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen, ...@@ -328,17 +332,13 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
ipv4 = 1;
} else { } else {
if(v4mapped(gate)) { if(v4mapped(gate)) {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
} ipv4 = 0;
if(v4mapped(gate)) {
/* Not implemented yet. */
errno = ENOSYS;
return -1;
} }
if(operation == ROUTE_MODIFY && newmetric == metric && if(operation == ROUTE_MODIFY && newmetric == metric &&
...@@ -396,30 +396,62 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen, ...@@ -396,30 +396,62 @@ kernel_route(int operation, const unsigned char *dest, unsigned short plen,
rtm->rtm_addrs |= RTA_NETMASK; rtm->rtm_addrs |= RTA_NETMASK;
} }
sin6 = (struct sockaddr_in6 *)&msg[sizeof(struct rt_msghdr)]; #define push_sockaddr_in(ptr, offset) \
/* Destination */ do { (ptr) = (struct sockaddr_in *)((char *)(ptr) + (offset)); \
sin6->sin6_len = sizeof(struct sockaddr_in6); (ptr)->sin_len = sizeof(struct sockaddr_in); \
sin6->sin6_family = AF_INET6; (ptr)->sin_family = AF_INET; } while (0)
sin6->sin6_addr = *((struct in6_addr *)dest);
sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); #define get_sin_addr(dst,src) \
/* Gateway */ do { memcpy((dst), (src) + 12, 4); } while (0)
sin6->sin6_len = sizeof(struct sockaddr_in6);
sin6->sin6_family = AF_INET6; #define push_sockaddr_in6(ptr, offset) \
if (metric == KERNEL_INFINITY) do { (ptr) = (struct sockaddr_in6 *)((char *)(ptr) + (offset)); \
sin6->sin6_addr = *((struct in6_addr *)*local); (ptr)->sin6_len = sizeof(struct sockaddr_in6); \
else (ptr)->sin6_family = AF_INET6; } while (0)
sin6->sin6_addr = *((struct in6_addr *)gate);
if(IN6_IS_ADDR_LINKLOCAL (&sin6->sin6_addr)) #define get_sin6_addr(dst,src) \
SET_IN6_LINKLOCAL_IFINDEX (sin6->sin6_addr, ifindex); do { memcpy((dst), (src), 16); } while (0)
sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len));
/* Netmask */ /* KAME ipv6 stack does not support IPv4 mapped IPv6, so we have to */
if((rtm->rtm_addrs | RTA_NETMASK) != 0) { if(ipv4) {
sin6->sin6_len = sizeof(struct sockaddr_in6); sin4 = (struct sockaddr_in *)msg;
sin6->sin6_family = AF_INET6; /* destination */
plen2mask(plen, &sin6->sin6_addr); push_sockaddr_in(sin4, sizeof(*rtm));
sin6 = (struct sockaddr_in6 *)((char *)sin6 + ROUNDUP(sin6->sin6_len)); get_sin_addr(&(sin4->sin_addr), dest);
/* gateway */
push_sockaddr_in(sin4, ROUNDUP(sin4->sin_len));
if (metric == KERNEL_INFINITY)
get_sin_addr(&(sin4->sin_addr),**local4);
else
get_sin_addr(&(sin4->sin_addr),gate);
/* netmask */
if((rtm->rtm_addrs | RTA_NETMASK) != 0) {
struct in6_addr tmp_sin6_addr;
push_sockaddr_in(sin4, ROUNDUP(sin4->sin_len));
plen2mask(plen, &tmp_sin6_addr);
get_sin_addr(&(sin4->sin_addr), (char *)&tmp_sin6_addr);
}
len = (char *)sin4 + ROUNDUP(sin4->sin_len) - (char *)msg;
} else {
sin6 = (struct sockaddr_in6 *)msg;
/* destination */
push_sockaddr_in6(sin6, sizeof(*rtm));
get_sin6_addr(&(sin6->sin6_addr), dest);
/* gateway */
push_sockaddr_in6(sin6, ROUNDUP(sin6->sin6_len));
if (metric == KERNEL_INFINITY)
get_sin6_addr(&(sin6->sin6_addr),**local6);
else
get_sin6_addr(&(sin6->sin6_addr),gate);
if(IN6_IS_ADDR_LINKLOCAL (&sin6->sin6_addr))
SET_IN6_LINKLOCAL_IFINDEX (sin6->sin6_addr, ifindex);
/* netmask */
if((rtm->rtm_addrs | RTA_NETMASK) != 0) {
push_sockaddr_in6(sin6, ROUNDUP(sin6->sin6_len));
plen2mask(plen, &sin6->sin6_addr);
}
len = (char *)sin6 + ROUNDUP(sin6->sin6_len) - (char *)msg;
} }
len = (char *)sin6 - (char *)msg;
rtm->rtm_msglen = len; rtm->rtm_msglen = len;
rc = write(kernel_socket, msg, rtm->rtm_msglen); rc = write(kernel_socket, msg, rtm->rtm_msglen);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment