# 2019q1 Homework5 (daemon)
contributed by < `shengyuu` >
- [作業要求](https://hackmd.io/s/SkLygcAiV)
按照作業要求下載並編譯 `kecho`
```
$ git clone https://github.com/sysprog21/kecho
$ cd kecho
$ make
```
## `kecho` 程式碼 實作的缺失
先將 `fastecho.ko` 核心模組載入,並使用 `telnet` 命令連接到 `localhost`
```
$ sudo insmod fastecho.ko
$ telnet localhost 12345
```
其中 `12345` 是 `port number`,定義在 `fastecho_module.c` 內
```c
#define DEFAULT_PORT 12345
```
執行 `telnet` 命令後會出現這樣的視窗
```
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
```
試著在這裡輸入任意字串
```
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hello!
hello!
��k
```
**從這裡可以觀察到 `kecho` 傳送回來的字串會包含奇怪的字元**
追蹤 `echo_server.c` 後可以發現 `kecho` 是用 `get_request()` 函式接收我們輸入的訊息,並透過 `send_request()` 傳回我們輸入的訊息,並將訊息用 `printk` 印出
``` c
/* get msg */
static int get_request(struct socket *sock, unsigned char *buf, size_t size)
{
struct msghdr msg;
struct kvec vec;
int length;
/* kvec setting */
vec.iov_len = size;
vec.iov_base = buf;
/* msghdr setting */
msg.msg_name = 0;
msg.msg_namelen = 0;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
printk(MODULE_NAME ": start get response\n");
/* get msg */
length = kernel_recvmsg(sock, &msg, &vec, size, size, msg.msg_flags);
printk(MODULE_NAME ": get request = %s\n", buf);
//printk(MODULE_NAME "buf_size = %d\n", strlen(buf));
return length;
}
```
使用 `dmesg` 命令看 `printk` 印出的 `buf` 裡面裝了什麼
```
[ 2548.119722] fastecho: start get response
[ 2551.493945] fastecho: get request = hello!
\xb0\xd3k
V
[ 2551.493948] fastecho: start send request.
[ 2551.494001] fastecho: send request = hello!
\xb0\xd3k
V
[ 2551.494003] fastecho: start get response
```
原本預期 `buf` 只裝我們傳送過去的 `hello!` ,但看起來 `buf` 裡面還有存著其他東西並且一起並印出來
再仔細觀察可以發現 `hello!` 後面其實是先空了一行才印出其他字串,猜想 `hello!` 後面應該是接著一個 `\n` ,而 `\n` 應該是我們輸入完字串按下 `enter` 鍵後產生的
我們可以利用每次輸入最後都會按下的 `enter` 鍵來觀察未初始化的 `buf` 中那一些值是我們要的值,哪一些對我們來說是亂碼
在 `echo_server.c` 中的 `get_request()` 函式內,手動將 `kernel_recvmsg` 拿到的 `buf` 的 `\n` 改成 `\0`,以下是更改後的 `get_request`
```c
static int get_request(struct socket *sock, unsigned char *buf, size_t size)
{
struct msghdr msg;
struct kvec vec;
int length;
/* kvec setting */
vec.iov_len = size;
vec.iov_base = buf;
/* msghdr setting */
msg.msg_name = 0;
msg.msg_namelen = 0;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_flags = 0;
printk(MODULE_NAME ": start get response\n");
/* get msg */
length = kernel_recvmsg(sock, &msg, &vec, size, size, msg.msg_flags);
/* replace '\n' by '\0'*/
int l = 0;
while(1)
{
if(buf[l] == '\n')
{
buf[l] = '\0';
break;
}
l++;
}
printk(MODULE_NAME ": get request = %s\n", buf);
//printk(MODULE_NAME "buf_size = %d\n", strlen(buf));
return length;
}
```
測試實驗結果
```
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hello!
hello!
```
```
$dmesg
[ 4827.660377] fastecho: socket create ok....
[ 4827.660382] fastecho: setsockopt ok....
[ 4827.660386] fastecho: socket bind ok....
[ 4827.660390] fastecho: socket listen ok....
[ 4843.881880] fastecho: start get response
[ 4848.824884] fastecho: get request = hello!
[ 4848.824889] fastecho: start send request.
[ 4848.824940] fastecho: send request = hello!
[ 4848.824944] fastecho: start get response
```
###### tags: `Linux 核心設計 2019`