78a8b3197b86281718553e96703c118c73a6f4fe
[libcmdline.git] / src / lib / cmdline_socket.c
1 /*
2  * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
3  * All rights reserved.
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of the University of California, Berkeley nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include <stdio.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32 #include <stdarg.h>
33 #include <inttypes.h>
34 #include <fcntl.h>
35
36 #include <sys/socket.h>
37 #include <netinet/in.h>
38 #include <sys/socket.h>
39 #include <sys/un.h>
40
41 #include "cmdline_parse.h"
42 #include "cmdline_rdline.h"
43 #include "cmdline.h"
44
45 /**********************/
46
47 int
48 cmdline_tcpv4_listen(in_addr_t addr, uint16_t port)
49 {
50         int s;
51         struct sockaddr_in sin_ci;
52         int optval = 1;
53
54         s = socket(PF_INET, SOCK_STREAM, 0);
55         if (s < 0) {
56                 dprintf("socket() failed\n");
57                 return s;
58         }
59
60         if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
61                        &optval, sizeof(optval)) == -1) {
62                 dprintf("setsockopt() failed\n");
63                 goto end;
64         }
65
66         memset(&sin_ci, 0, sizeof(sin_ci));
67         sin_ci.sin_family = AF_INET;
68         sin_ci.sin_addr.s_addr = addr;
69         sin_ci.sin_port = htons(port);
70 #ifndef __linux__
71         sin_ci.sin_len = sizeof(sin_ci);
72 #endif
73         if (bind(s, (struct sockaddr *)&sin_ci, sizeof(sin_ci)) < 0) {
74                 dprintf("bind() failed\n");
75                 goto end;
76         }
77
78         if (listen(s, 1) < 0) {
79                 dprintf("listen() failed\n");
80                 goto end;
81         }
82
83         return s;
84 end:
85         close(s);
86         return -1;
87 }
88
89 int
90 cmdline_tcpv6_listen(struct in6_addr addr6, uint16_t port)
91 {
92         int s;
93         struct sockaddr_in6 sin6_ci;
94
95         s = socket(PF_INET6, SOCK_STREAM, 0);
96         if (s < 0) {
97                 dprintf("socket() failed\n");
98                 return s;
99         }
100
101         bzero(&sin6_ci, sizeof(sin6_ci));
102         sin6_ci.sin6_family = AF_INET6;
103 #ifndef __linux__
104         sin6_ci.sin6_len = sizeof(sin6_ci);
105 #endif
106         memcpy(&sin6_ci.sin6_addr, &addr6, sizeof(sin6_ci.sin6_addr));
107         sin6_ci.sin6_port = htons(port);
108         if (bind(s, (struct sockaddr *) &sin6_ci, sizeof(sin6_ci)) < 0) {
109                 dprintf("bind() failed\n");
110                 goto end;
111         }
112
113         if (listen(s, 1) < 0) {
114                 dprintf("listen() failed\n");
115                 goto end;
116         }
117
118         return s;
119 end:
120         close(s);
121         return -1;
122 }
123
124 int
125 cmdline_unix_listen(char *filename)
126 {
127         int s;
128         struct sockaddr_un servAddr;
129
130         s = socket(AF_UNIX, SOCK_STREAM, 0);
131         if (s < 0) {
132                 dprintf("socket() failed\n");
133                 return s;
134         }
135
136         bzero(&servAddr, sizeof(servAddr));
137         servAddr.sun_family = AF_UNIX;
138         memcpy(servAddr.sun_path, filename , strlen(filename));
139         
140         unlink(filename);
141         if(bind(s, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0) {
142                 dprintf("bind() failed\n");
143                 goto end;
144         }
145
146         if (listen(s, 1) < 0) {
147                 dprintf("listen() failed\n");
148                 goto end;
149         }
150
151         return s;
152 end:
153         close(s);
154         return -1;
155 }
156
157 struct cmdline *
158 cmdline_stdin_new(cmdline_parse_ctx_t *ctx, const char *prompt)
159 {
160         return (cmdline_new(ctx, prompt, 0, 1));
161 }
162
163 struct cmdline *
164 cmdline_file_new(cmdline_parse_ctx_t *ctx, const char *prompt, const char *path)
165 {
166         int fd;
167         fd = open(path, O_RDONLY, 0);
168         if (fd < 0) {
169                 dprintf("open() failed\n");
170                 return NULL;
171         }
172         return (cmdline_new(ctx, prompt, fd, -1));
173 }
174
175 struct cmdline *
176 cmdline_accept(cmdline_parse_ctx_t *ctx, const char *prompt, int s)
177 {
178         int s2;
179         struct sockaddr sin;
180         socklen_t sinlen;
181
182         sinlen = sizeof(struct sockaddr);
183
184         if ((s2 = accept(s, &sin, &sinlen)) < 0) {
185                 dprintf("accept() failed\n");
186                 return NULL;
187         }
188
189         return (cmdline_new(ctx, prompt, s2, s2));
190 }
191