Skip to content

Instantly share code, notes, and snippets.

@jangsoopark
Last active October 13, 2016 16:35
Show Gist options
  • Save jangsoopark/4f8114458525787ed231e593f3b284e4 to your computer and use it in GitHub Desktop.
Save jangsoopark/4f8114458525787ed231e593f3b284e4 to your computer and use it in GitHub Desktop.
ksocket (kerner socket library) reference : http://ksocket.sourceforge.net/
/*
* 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;
}
/*
* 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