tools: Add utility for testing AF_ALG kernel interface
[platform/upstream/connman.git] / tools / alg-test.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <fcntl.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <sys/stat.h>
31 #include <sys/mman.h>
32 #include <sys/socket.h>
33 #include <linux/if_alg.h>
34
35 static void build_hash(int sk, char *map, size_t size, const char *pathname)
36 {
37         unsigned char hash[20];
38         ssize_t written, length;
39         int i;
40
41         written = send(sk, map, size, 0);
42         if (written < 0)
43                 perror("Failed to write data");
44
45         printf("send %zd bytes\n", written);
46
47         length = recv(sk, hash, sizeof(hash), 0);
48         if (length < 0)
49                 perror("Failed to read data");
50
51         printf("recv %zd bytes\n", length);
52
53         for (i = 0; i < length; i++)
54                 printf("%02x", hash[i]);
55         printf("  %s\n", pathname);
56 }
57
58 static int create_hash(int sk, const char *pathname)
59 {
60         struct stat st;
61         char *map;
62         int fd;
63
64         fd = open(pathname, O_RDONLY);
65         if (fd < 0)
66                 return -1;
67
68         if (fstat(fd, &st) < 0) {
69                 close(fd);
70                 return -1;
71         }
72
73         map = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
74         if (map == NULL || map == MAP_FAILED) {
75                 close(fd);
76                 return -1;
77         }
78
79         build_hash(sk, map, st.st_size, pathname);
80
81         munmap(map, st.st_size);
82
83         close(fd);
84
85         return 0;
86 }
87
88 static int create_socket(void)
89 {
90         struct sockaddr_alg salg = {
91                 .salg_family = AF_ALG,
92                 .salg_type = "hash",
93                 .salg_name = "sha1",
94         };
95         int sk, nsk;
96
97         sk = socket(PF_ALG, SOCK_SEQPACKET, 0);
98         if (sk < 0) {
99                 perror("Failed to create socket");
100                 return -1;
101         }
102
103         if (bind(sk, (struct sockaddr *) &salg, sizeof(salg)) < 0) {
104                 perror("Failed to bind socket");
105                 close(sk);
106                 return -1;
107         }
108
109         nsk = accept(sk, NULL, 0);
110         if (nsk < 0) {
111                 perror("Failed to accept socket");
112                 close(sk);
113                 return -1;
114         }
115
116         close(sk);
117
118         return nsk;
119 }
120
121 int main(int argc, char *argv[])
122 {
123         int sk;
124
125         if (argc < 2) {
126                 fprintf(stderr, "Missing argument\n");
127                 return 1;
128         }
129
130         sk = create_socket();
131         if (sk < 0)
132                 return 1;
133
134         create_hash(sk, argv[1]);
135
136         close(sk);
137
138         return 0;
139 }