Last active
October 13, 2016 16:35
-
-
Save jangsoopark/4f8114458525787ed231e593f3b284e4 to your computer and use it in GitHub Desktop.
ksocket (kerner socket library) reference : http://ksocket.sourceforge.net/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* ksocket project | |
* BSD-style socket APIs for kernel 2.6 developers | |
* | |
* @2007-2008, China | |
* @song.xian-guang@hotmail.com (MSN Accounts) | |
* | |
* This code is licenced under the GPL | |
* Feel free to contact me if any questions | |
* | |
* @2015, Korea | |
* @wkdtn8211@gmail.com | |
* | |
* jangsoo park rewrite for | |
* linux kernel version over 3.19.00 | |
*/ | |
#include <linux/version.h> | |
#include <linux/module.h> | |
#include <linux/string.h> | |
#include <linux/socket.h> | |
#include <linux/net.h> | |
#include <linux/in.h> | |
#include <net/sock.h> | |
#include <asm/processor.h> | |
#include <asm/uaccess.h> | |
#include "ksocket.h" | |
ksocket_t ksocket(int domain, int type, int protocol) | |
{ | |
struct socket *sk = NULL; | |
int ret = 0; | |
ret = sock_create(domain, type, protocol, &sk); | |
if (ret < 0) | |
{ | |
return NULL; | |
} | |
return sk; | |
} | |
int kbind(ksocket_t socket, struct sockaddr *address, int address_len) | |
{ | |
struct socket *sk; | |
int ret = 0; | |
sk = (struct socket *)socket; | |
ret = sk->ops->bind(sk, address, address_len); | |
return ret; | |
} | |
int klisten(ksocket_t socket, int backlog) | |
{ | |
struct socket *sk; | |
int ret; | |
sk = (struct socket *)socket; | |
if ((unsigned)backlog > SOMAXCONN) | |
backlog = SOMAXCONN; | |
ret = sk->ops->listen(sk, backlog); | |
return ret; | |
} | |
int kconnect(ksocket_t socket, struct sockaddr *address, int address_len) | |
{ | |
struct socket *sk; | |
int ret; | |
sk = (struct socket *)socket; | |
ret = sk->ops->connect(sk, address, address_len, 0/*sk->file->f_flags*/); | |
return ret; | |
} | |
ksocket_t kaccept(ksocket_t socket, struct sockaddr *address, int *address_len) | |
{ | |
struct socket *sk; | |
struct socket *new_sk = NULL; | |
int ret; | |
sk = (struct socket *)socket; | |
//new_sk = sock_alloc(); | |
//sock_alloc() is not exported, so i use sock_create() instead | |
ret = sock_create(sk->sk->sk_family, sk->type, sk->sk->sk_protocol, &new_sk); | |
if (ret < 0) | |
return NULL; | |
if (!new_sk) | |
return NULL; | |
new_sk->type = sk->type; | |
new_sk->ops = sk->ops; | |
ret = sk->ops->accept(sk, new_sk, 0 /*sk->file->f_flags*/); | |
if (ret < 0) | |
goto error_kaccept; | |
if (address) | |
{ | |
ret = new_sk->ops->getname(new_sk, address, address_len, 2); | |
if (ret < 0) | |
goto error_kaccept; | |
} | |
return new_sk; | |
error_kaccept: | |
sock_release(new_sk); | |
return NULL; | |
} | |
ssize_t krecv(ksocket_t socket, void *buffer, size_t length, int flags) | |
{ | |
struct socket *sk; | |
struct msghdr msg; | |
#if LINUX_VERSION_CODE > KERNEL_VERSION(3,19,00) | |
struct iov_iter iovi; | |
#endif | |
struct iovec iov; | |
int ret; | |
#ifndef KSOCKET_ADDR_SAFE | |
mm_segment_t old_fs; | |
#endif | |
sk = (struct socket *)socket; | |
iov.iov_base = (void *)buffer; | |
iov.iov_len = (__kernel_size_t)length; | |
msg.msg_name = NULL; | |
msg.msg_namelen = 0; | |
#if LINUX_VERSION_CODE > KERNEL_VERSION(3,19,00) | |
iovi.iov = &iov; | |
msg.msg_iter = iovi; | |
#else | |
msg.msg_iov = &iov; | |
msg.msg_iovlen = 1; | |
#endif | |
msg.msg_control = NULL; | |
msg.msg_controllen = 0; | |
/* | |
* msg.msg_iov->iov_base is declared as follows: | |
* void __user *iov_base; | |
* which means there is an user space pointer in 'msg' | |
* use set_fs(KERNEL_DS) to make the pointer safe to kernel space | |
*/ | |
#ifndef KSOCKET_ADDR_SAFE | |
old_fs = get_fs(); | |
set_fs(KERNEL_DS); | |
#endif | |
ret = sock_recvmsg(sk, &msg, length, flags); | |
#ifndef KSOCKET_ADDR_SAFE | |
set_fs(old_fs); | |
#endif | |
if (ret < 0) | |
goto out_krecv; | |
//ret = msg.msg_iov.iov_len;//? | |
out_krecv: | |
return ret; | |
} | |
ssize_t ksend(ksocket_t socket, const void *buffer, size_t length, int flags) | |
{ | |
struct socket *sk; | |
struct msghdr msg; | |
#if LINUX_VERSION_CODE > KERNEL_VERSION(3,19,00) | |
struct iov_iter iovi; | |
#endif | |
struct iovec iov; | |
int len; | |
#ifndef KSOCKET_ADDR_SAFE | |
mm_segment_t old_fs; | |
#endif | |
sk = (struct socket *)socket; | |
iov.iov_base = (void *)buffer; | |
iov.iov_len = (__kernel_size_t)length; | |
msg.msg_name = NULL; | |
msg.msg_namelen = 0; | |
#if LINUX_VERSION_CODE > KERNEL_VERSION(3,19,00) | |
iovi.iov = &iov; | |
msg.msg_iter = iovi; | |
#else | |
msg.msg_iov = &iov; | |
msg.msg_iovlen = 1; | |
#endif | |
msg.msg_control = NULL; | |
msg.msg_controllen = 0; | |
msg.msg_flags = flags; | |
#ifndef KSOCKET_ADDR_SAFE | |
old_fs = get_fs(); | |
set_fs(KERNEL_DS); | |
#endif | |
len = sock_sendmsg(sk, &msg, length);//? | |
#ifndef KSOCKET_ADDR_SAFE | |
set_fs(old_fs); | |
#endif | |
return len;//len ? | |
} | |
int kshutdown(ksocket_t socket, int how) | |
{ | |
struct socket *sk; | |
int ret = 0; | |
sk = (struct socket *)socket; | |
if (sk) | |
ret = sk->ops->shutdown(sk, how); | |
return ret; | |
} | |
//TODO: ? | |
int kclose(ksocket_t socket) | |
{ | |
struct socket *sk; | |
int ret; | |
sk = (struct socket *)socket; | |
ret = sk->ops->release(sk); | |
if (sk) | |
sock_release(sk); | |
return ret; | |
} | |
ssize_t krecvfrom(ksocket_t socket, void * buffer, size_t length, | |
int flags, struct sockaddr * address, | |
int * address_len) | |
{ | |
struct socket *sk; | |
struct msghdr msg; | |
struct iovec iov; | |
#if LINUX_VERSION_CODE > KERNEL_VERSION(3,19,00) | |
struct iov_iter iovi; | |
#endif | |
int len; | |
#ifndef KSOCKET_ADDR_SAFE | |
mm_segment_t old_fs; | |
#endif | |
sk = (struct socket *)socket; | |
iov.iov_base = (void *)buffer; | |
iov.iov_len = (__kernel_size_t)length; | |
msg.msg_name = address; | |
msg.msg_namelen = 128; | |
#if LINUX_VERSION_CODE > KERNEL_VERSION(3,19,00) | |
iovi.iov = &iov; | |
msg.msg_iter = iovi; | |
#else | |
msg.msg_iov = &iov; | |
msg.msg_iovlen = 1; | |
#endif | |
msg.msg_control = NULL; | |
msg.msg_controllen = 0; | |
#ifndef KSOCKET_ADDR_SAFE | |
old_fs = get_fs(); | |
set_fs(KERNEL_DS); | |
#endif | |
len = sock_recvmsg(sk, &msg, length, flags); | |
#ifndef KSOCKET_ADDR_SAFE | |
set_fs(old_fs); | |
#endif | |
if (address) | |
{ | |
*address_len = msg.msg_namelen; | |
} | |
return len; | |
} | |
ssize_t ksendto(ksocket_t socket, void *message, size_t length, | |
int flags, const struct sockaddr *dest_addr, | |
int dest_len) | |
{ | |
struct socket *sk; | |
struct msghdr msg; | |
struct iovec iov; | |
#if LINUX_VERSION_CODE > KERNEL_VERSION(3,19,00) | |
struct iov_iter iovi; | |
#endif | |
int len; | |
#ifndef KSOCKET_ADDR_SAFE | |
mm_segment_t old_fs; | |
#endif | |
sk = (struct socket *)socket; | |
iov.iov_base = (void *)message; | |
iov.iov_len = (__kernel_size_t)length; | |
#if LINUX_VERSION_CODE > KERNEL_VERSION(3,19,00) | |
iovi.iov = &iov; | |
msg.msg_iter = iovi; | |
#else | |
msg.msg_iov = &iov; | |
msg.msg_iovlen = 1; | |
#endif | |
msg.msg_control = NULL; | |
msg.msg_controllen = 0; | |
msg.msg_flags = flags; | |
if (dest_addr) | |
{ | |
msg.msg_name = (void *)dest_addr; | |
msg.msg_namelen = dest_len; | |
} | |
#ifndef KSOCKET_ADDR_SAFE | |
old_fs = get_fs(); | |
set_fs(KERNEL_DS); | |
#endif | |
len = sock_sendmsg(sk, &msg, length);//? | |
#ifndef KSOCKET_ADDR_SAFE | |
set_fs(old_fs); | |
#endif | |
return len;//len ? | |
} | |
int kgetsockname(ksocket_t socket, struct sockaddr *address, int *address_len) | |
{ | |
struct socket *sk; | |
int ret; | |
sk = (struct socket *)socket; | |
ret = sk->ops->getname(sk, address, address_len, 0); | |
return ret; | |
} | |
int kgetpeername(ksocket_t socket, struct sockaddr *address, int *address_len) | |
{ | |
struct socket *sk; | |
int ret; | |
sk = (struct socket *)socket; | |
ret = sk->ops->getname(sk, address, address_len, 1); | |
return ret; | |
} | |
int ksetsockopt(ksocket_t socket, int level, int optname, void *optval, int optlen) | |
{ | |
struct socket *sk; | |
int ret; | |
#ifndef KSOCKET_ADDR_SAFE | |
mm_segment_t old_fs; | |
#endif | |
sk = (struct socket *)socket; | |
#ifndef KSOCKET_ADDR_SAFE | |
old_fs = get_fs(); | |
set_fs(KERNEL_DS); | |
#endif | |
if (level == SOL_SOCKET) | |
ret = sock_setsockopt(sk, level, optname, optval, optlen); | |
else | |
ret = sk->ops->setsockopt(sk, level, optname, optval, optlen); | |
#ifndef KSOCKET_ADDR_SAFE | |
set_fs(old_fs); | |
#endif | |
return ret; | |
} | |
int kgetsockopt(ksocket_t socket, int level, int optname, void *optval, int *optlen) | |
{ | |
/* struct socket *sk; | |
int ret; | |
mm_segment_t old_fs; | |
sk = (struct socket *)socket; | |
old_fs = get_fs(); | |
set_fs(KERNEL_DS); | |
if (level == SOL_SOCKET) | |
ret = sock_getsockopt(sk, level, optname, optval, optlen); | |
else | |
ret = sk->ops->getsockopt(sk, level, optname, optval, optlen); | |
set_fs(old_fs); | |
return ret; | |
*/ | |
return -ENOSYS; | |
} | |
//helper functions | |
unsigned int inet_addr(char* ip) | |
{ | |
int a, b, c, d; | |
char addr[4]; | |
sscanf(ip, "%d.%d.%d.%d", &a, &b, &c, &d); | |
addr[0] = a; | |
addr[1] = b; | |
addr[2] = c; | |
addr[3] = d; | |
return *(unsigned int *)addr; | |
} | |
char *inet_ntoa(struct in_addr *in) | |
{ | |
char* str_ip = NULL; | |
u_int32_t int_ip = 0; | |
str_ip = kmalloc(16 * sizeof(char), GFP_KERNEL); | |
if (!str_ip) | |
return NULL; | |
else | |
memset(str_ip, 0, 16); | |
int_ip = in->s_addr; | |
sprintf(str_ip, "%d.%d.%d.%d", (int_ip ) & 0xFF, | |
(int_ip >> 8 ) & 0xFF, | |
(int_ip >> 16) & 0xFF, | |
(int_ip >> 24) & 0xFF); | |
return str_ip; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* ksocket project | |
* BSD-style socket APIs for kernel 2.6 developers | |
* | |
* @2007-2008, China | |
* @song.xian-guang@hotmail.com (MSN Accounts) | |
* | |
* This code is licenced under the GPL | |
* Feel free to contact me if any questions | |
* | |
* @2015, Korea | |
* @wkdtn8211@gmail.com | |
* | |
* jangsoo park rewrite for | |
* linux kernel version over 3.19.00 | |
*/ | |
#ifndef _ksocket_h_ | |
#define _ksocket_h_ | |
#include <linux/types.h> | |
struct socket; | |
struct sockaddr; | |
struct in_addr; | |
typedef struct socket * ksocket_t; | |
/* BSD socket APIs prototype declaration */ | |
ksocket_t ksocket(int domain, int type, int protocol); | |
int kshutdown(ksocket_t socket, int how); | |
int kclose(ksocket_t socket); | |
int kbind(ksocket_t socket, struct sockaddr *address, int address_len); | |
int klisten(ksocket_t socket, int backlog); | |
int kconnect(ksocket_t socket, struct sockaddr *address, int address_len); | |
ksocket_t kaccept(ksocket_t socket, struct sockaddr *address, int *address_len); | |
ssize_t krecv(ksocket_t socket, void *buffer, size_t length, int flags); | |
ssize_t ksend(ksocket_t socket, const void *buffer, size_t length, int flags); | |
ssize_t krecvfrom(ksocket_t socket, void * buffer, size_t length, int flags, struct sockaddr * address, int * address_len); | |
ssize_t ksendto(ksocket_t socket, void *message, size_t length, int flags, const struct sockaddr *dest_addr, int dest_len); | |
int kgetsockname(ksocket_t socket, struct sockaddr *address, int *address_len); | |
int kgetpeername(ksocket_t socket, struct sockaddr *address, int *address_len); | |
int ksetsockopt(ksocket_t socket, int level, int optname, void *optval, int optlen); | |
int kgetsockopt(ksocket_t socket, int level, int optname, void *optval, int *optlen); | |
unsigned int inet_addr(char* ip); | |
char *inet_ntoa(struct in_addr *in); /* DO NOT forget to kfree the return pointer */ | |
#endif /* !_ksocket_h_ */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment