Skip to content

Commit 7a44871

Browse files
authored
added client AF_UNIX socket support (#31)
1 parent 02ad0f5 commit 7a44871

1 file changed

Lines changed: 73 additions & 21 deletions

File tree

socketcandcl.c

Lines changed: 73 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
#include <sys/socket.h>
6161
#include <sys/ioctl.h>
6262
#include <sys/uio.h>
63+
#include <sys/un.h>
6364
#include <net/if.h>
6465
#include <netinet/in.h>
6566
#include <netinet/tcp.h>
@@ -100,16 +101,20 @@ int main(int argc, char **argv)
100101
{
101102
int i;
102103
struct sockaddr_in serveraddr;
104+
struct sockaddr_un serveraddr_un;
105+
socklen_t serveraddr_un_len;
103106
struct hostent *server_ent;
104107
struct sigaction sigint_action;
105108
char buf[MAXLEN];
106109
char* server_string;
110+
char* afuxname;
107111

108112
/* set default config settings */
109113
port = PORT;
110114
strcpy(ldev, "can0");
111115
strcpy(rdev, "can0");
112116
server_string = malloc(strlen("localhost"));
117+
afuxname = NULL;
113118

114119

115120
/* Parse commandline arguments */
@@ -119,13 +124,14 @@ int main(int argc, char **argv)
119124
static struct option long_options[] = {
120125
{"verbose", no_argument, 0, 'v'},
121126
{"interfaces", required_argument, 0, 'i'},
127+
{"afuxname", required_argument, 0, 'u'},
122128
{"server", required_argument, 0, 's'},
123129
{"port", required_argument, 0, 'p'},
124130
{"version", no_argument, 0, 'z'},
125131
{0, 0, 0, 0}
126132
};
127133

128-
c = getopt_long(argc, argv, "vhi:p:l:s:", long_options, &option_index);
134+
c = getopt_long(argc, argv, "vhi:p:l:s:u:", long_options, &option_index);
129135

130136
if(c == -1)
131137
break;
@@ -146,6 +152,11 @@ int main(int argc, char **argv)
146152
port = atoi(optarg);
147153
break;
148154

155+
case 'u':
156+
afuxname = realloc(afuxname, strlen(optarg)+1);
157+
strcpy(afuxname, optarg);
158+
break;
159+
149160
case 's':
150161
server_string = realloc(server_string, strlen(optarg)+1);
151162
strcpy(server_string, optarg);
@@ -180,30 +191,70 @@ int main(int argc, char **argv)
180191
sigint_action.sa_flags = 0;
181192
sigaction(SIGINT, &sigint_action, NULL);
182193

183-
server_socket = socket(AF_INET, SOCK_STREAM, 0);
184-
if(server_socket < 0) {
185-
perror("socket");
186-
exit(1);
187-
}
188194

189-
memset(&serveraddr, 0, sizeof(serveraddr));
190-
serveraddr.sin_family = AF_INET;
191-
serveraddr.sin_port = htons(port);
195+
if (afuxname) {
196+
/* create AF_UNIX socket */
197+
server_socket = socket(AF_UNIX, SOCK_STREAM, 0);
198+
if(server_socket < 0) {
199+
perror("unixsocket");
200+
exit(1);
201+
}
192202

193-
server_ent = gethostbyname(server_string);
194-
if(server_ent == 0) {
195-
perror(server_string);
196-
exit(1);
197-
}
203+
serveraddr_un.sun_family = AF_UNIX;
204+
if (strlen(afuxname) > sizeof(serveraddr_un.sun_path)-3) {
205+
printf("afuxname is too long.\n");
206+
exit(1);
207+
}
198208

199-
memcpy(&(serveraddr.sin_addr.s_addr), server_ent->h_addr,
200-
server_ent->h_length);
209+
/* when the given afuxname starts with a '/' we assume the path name scheme, e.g.
210+
* /var/run/socketcand or /tmp/socketcand-afunix-socket
211+
* Without the leading '/' we use the string as abstract socket address.
212+
*/
201213

214+
if (afuxname[0] == '/') {
215+
strcpy(&serveraddr_un.sun_path[0], afuxname);
216+
/* due to the trailing \0 in path name definition we can write the entire struct */
217+
serveraddr_un_len = sizeof(serveraddr_un);
218+
} else {
219+
strcpy(&serveraddr_un.sun_path[1], afuxname);
220+
serveraddr_un.sun_path[0] = 0;
221+
/* abtract name length definition without trailing \0 but with leading \0 */
222+
serveraddr_un_len = strlen(afuxname) + sizeof(serveraddr_un.sun_family) + 1;
223+
}
202224

203-
if(connect(server_socket, (struct sockaddr*)&serveraddr,
204-
sizeof(serveraddr)) != 0) {
205-
perror("connect");
206-
exit(1);
225+
if(connect(server_socket, (struct sockaddr*)&serveraddr_un, serveraddr_un_len) != 0) {
226+
perror("connect");
227+
exit(1);
228+
}
229+
}
230+
else {
231+
/* create AF_INET socket */
232+
233+
server_socket = socket(AF_INET, SOCK_STREAM, 0);
234+
if(server_socket < 0) {
235+
perror("socket");
236+
exit(1);
237+
}
238+
239+
memset(&serveraddr, 0, sizeof(serveraddr));
240+
serveraddr.sin_family = AF_INET;
241+
serveraddr.sin_port = htons(port);
242+
243+
server_ent = gethostbyname(server_string);
244+
if(server_ent == 0) {
245+
perror(server_string);
246+
exit(1);
247+
}
248+
249+
memcpy(&(serveraddr.sin_addr.s_addr), server_ent->h_addr,
250+
server_ent->h_length);
251+
252+
253+
if(connect(server_socket, (struct sockaddr*)&serveraddr,
254+
sizeof(serveraddr)) != 0) {
255+
perror("connect");
256+
exit(1);
257+
}
207258
}
208259

209260

@@ -500,12 +551,13 @@ int receive_command(int socket, char *buffer)
500551

501552
void print_usage(void)
502553
{
503-
printf("Usage: socketcandcl [-v | --verbose] [-i interfaces | --interfaces interfaces]\n\t\t[-s server | --server server ]\n\t\t[-p port | --port port]\n");
554+
printf("Usage: socketcandcl [-v | --verbose] [-i interfaces | --interfaces interfaces]\n\t\t[-s server | --server server ] [-u name | --afuxname name]\n\t\t[-p port | --port port]\n");
504555
printf("Options:\n");
505556
printf("\t-v activates verbose output to STDOUT\n");
506557
printf("\t-s server hostname\n");
507558
printf("\t-i SocketCAN interfaces to use: device_server,device_client \n");
508559
printf("\t-p port changes the default port (%d) the client connects to\n", PORT);
560+
printf("\t-u AF_UNIX socket path - abstract name when leading '/' is missing\n");
509561
printf("\t-h prints this message\n");
510562
}
511563

0 commit comments

Comments
 (0)