-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
From: https://github.com/moby/vpnkit commit 2ffc1dd8a84ea7359dd09b1f4b51bb728d4f46a0 c/vpnkit-tap-vsockd/protocol.h c/vpnkit-tap-vsockd/protocol.c
- Loading branch information
1 parent
5d6d9ee
commit 261249c
Showing
2 changed files
with
301 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,224 @@ | ||
#include <sys/socket.h> | ||
#include <sys/types.h> | ||
#include <sys/uio.h> | ||
#include <unistd.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <stdio.h> | ||
|
||
#include "log.h" | ||
#include "protocol.h" | ||
|
||
/* Version 0 of the protocol used this */ | ||
char expected_hello_old[5] = {'V', 'M', 'N', 'E', 'T'}; | ||
|
||
/* Version 1 and later of the protocol used this */ | ||
char expected_hello[5] = {'V', 'M', 'N', '3', 'T'}; | ||
|
||
int really_read(int fd, uint8_t *buffer, size_t total) | ||
{ | ||
size_t remaining = total; | ||
ssize_t n; | ||
|
||
while (remaining > 0) { | ||
n = read(fd, buffer, remaining); | ||
if (n == 0) { | ||
ERROR("EOF reading from socket: closing\n"); | ||
goto err; | ||
} | ||
if (n < 0) { | ||
ERROR( | ||
"Failure reading from socket: closing: %s", | ||
strerror(errno)); | ||
goto err; | ||
} | ||
remaining -= (size_t) n; | ||
buffer = buffer + n; | ||
} | ||
return 0; | ||
err: | ||
/* | ||
* On error: stop reading from the socket and trigger a clean | ||
* shutdown | ||
*/ | ||
shutdown(fd, SHUT_RD); | ||
return -1; | ||
} | ||
|
||
int really_write(int fd, uint8_t *buffer, size_t total) | ||
{ | ||
size_t remaining = total; | ||
ssize_t n; | ||
|
||
while (remaining > 0) { | ||
n = write(fd, buffer, remaining); | ||
if (n == 0) { | ||
ERROR("EOF writing to socket: closing"); | ||
goto err; | ||
} | ||
if (n < 0) { | ||
ERROR( | ||
"Failure writing to socket: closing: %s", | ||
strerror(errno)); | ||
goto err; | ||
} | ||
remaining -= (size_t) n; | ||
buffer = buffer + n; | ||
} | ||
return 0; | ||
err: | ||
/* On error: stop listening to the socket */ | ||
shutdown(fd, SHUT_WR); | ||
return -1; | ||
} | ||
|
||
struct init_message *create_init_message() | ||
{ | ||
struct init_message *m; | ||
|
||
m = malloc(sizeof(struct init_message)); | ||
if (!m) | ||
return NULL; | ||
|
||
bzero(m, sizeof(struct init_message)); | ||
memcpy(&m->hello[0], &expected_hello[0], sizeof(m->hello)); | ||
m->version = CURRENT_VERSION; | ||
memset(&m->commit[0], 0, sizeof(m->commit)); | ||
|
||
return m; | ||
} | ||
|
||
char *print_init_message(struct init_message *m) | ||
{ | ||
char tmp[41]; | ||
|
||
memcpy(&tmp[0], &m->commit[0], 40); | ||
tmp[40] = '\000'; | ||
char *buffer; | ||
int n; | ||
|
||
buffer = malloc(80); | ||
if (!buffer) | ||
return NULL; | ||
|
||
n = snprintf(buffer, 80, "version %d, commit %s", m->version, tmp); | ||
if (n < 0) { | ||
perror("Failed to format init_message"); | ||
exit(1); | ||
} | ||
return buffer; | ||
} | ||
|
||
int read_init_message(int fd, struct init_message *ci) | ||
{ | ||
int res; | ||
|
||
bzero(ci, sizeof(struct init_message)); | ||
|
||
res = really_read(fd, (uint8_t *)&ci->hello[0], sizeof(ci->hello)); | ||
if (res == -1) { | ||
ERROR("Failed to read hello from client"); | ||
return -1; | ||
} | ||
|
||
res = memcmp(&ci->hello[0], | ||
&expected_hello_old[0], sizeof(expected_hello_old)); | ||
if (res == 0) { | ||
ci->version = 0; | ||
return 0; | ||
} | ||
|
||
res = memcmp(&ci->hello[0], | ||
&expected_hello[0], sizeof(expected_hello)); | ||
if (res != 0) { | ||
ERROR("Failed to read header magic from client"); | ||
return -1; | ||
} | ||
|
||
res = really_read(fd, (uint8_t *)&ci->version, sizeof(ci->version)); | ||
if (res == -1) { | ||
ERROR("Failed to read header version from client"); | ||
return -1; | ||
} | ||
|
||
res = really_read(fd, (uint8_t *)&ci->commit[0], sizeof(ci->commit)); | ||
if (res == -1) { | ||
ERROR("Failed to read header hash from client"); | ||
return -1; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
int write_init_message(int fd, struct init_message *ci) | ||
{ | ||
int res; | ||
|
||
res = really_write(fd, (uint8_t *)&ci->hello[0], sizeof(ci->hello)); | ||
if (res == -1) { | ||
ERROR("Failed to write hello to client"); | ||
return -1; | ||
} | ||
if (ci->version > 0) { | ||
res = really_write(fd, (uint8_t *)&ci->version, | ||
sizeof(ci->version)); | ||
if (res == -1) { | ||
ERROR("Failed to write version to client"); | ||
return -1; | ||
} | ||
res = really_write(fd, (uint8_t *)&ci->commit[0], | ||
sizeof(ci->commit)); | ||
if (res == -1) { | ||
ERROR("Failed to write header hash to client"); | ||
return -1; | ||
} | ||
} | ||
return 0; | ||
} | ||
|
||
int read_vif_response(int fd, struct vif_info *vif) | ||
{ | ||
struct msg_response msg; | ||
|
||
if (really_read(fd, (uint8_t*)&msg, sizeof(msg)) == -1) { | ||
ERROR("Client failed to read server response"); | ||
return -1; | ||
} | ||
|
||
switch (msg.response_type) { | ||
case rt_vif: | ||
memcpy((uint8_t*)vif, (uint8_t*)&msg.vif, sizeof(*vif)); | ||
return 0; | ||
case rt_disconnect: | ||
ERROR("Server disconnected: %*s", msg.disconnect.len, msg.disconnect.msg); | ||
return -1; | ||
default: | ||
ERROR("Unknown response type from server"); | ||
return -1; | ||
} | ||
|
||
} | ||
|
||
int write_command(int fd, enum command *c) | ||
{ | ||
uint8_t command = *c; | ||
|
||
if (really_write(fd, (uint8_t *)&command, sizeof(command)) == -1) { | ||
ERROR("Failed to write command to client"); | ||
return -1; | ||
} | ||
return 0; | ||
} | ||
|
||
int write_ethernet_args(int fd, struct ethernet_args *args) | ||
{ | ||
uint8_t buffer[40]; | ||
memset(&buffer[0], 0, sizeof(buffer)); | ||
memcpy(&buffer[0], (uint8_t *)&args->uuid_string[0], 36); | ||
|
||
if (really_write(fd, (uint8_t *)&buffer, sizeof(buffer)) == -1) { | ||
ERROR("Failed to write ethernet args to client"); | ||
return -1; | ||
} | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
#ifndef _VMNET_PROTOCOL_H_ | ||
#define _VMNET_PROTOCOL_H_ | ||
|
||
#include <errno.h> | ||
#include <stdint.h> | ||
|
||
/* Client -> Server init_message */ | ||
/* Server -> Client init_message */ | ||
struct init_message { | ||
char hello[5]; | ||
uint8_t _padding[3]; | ||
uint32_t version; | ||
char commit[40]; /* git sha of the compiled commit */ | ||
}; | ||
|
||
/* | ||
* This should be bumped whenever we add something (like a feature or a | ||
* bugfix) and we wish the UI to be able to detect when to trigger a | ||
* reinstall. | ||
*/ | ||
#define CURRENT_VERSION 22 | ||
|
||
extern struct init_message *create_init_message(void); | ||
extern int read_init_message(int fd, struct init_message *ci); | ||
extern int write_init_message(int fd, struct init_message *ci); | ||
extern char *print_init_message(struct init_message *m); | ||
|
||
/* Client -> Server command */ | ||
enum command { | ||
ethernet = 1, | ||
}; | ||
|
||
/* Server -> Client response */ | ||
enum response_type { | ||
rt_vif = 1, | ||
rt_disconnect = 2, | ||
}; | ||
|
||
extern int write_command(int fd, enum command *c); | ||
|
||
/* Client -> Server command arguments */ | ||
struct ethernet_args { | ||
char uuid_string[36]; | ||
}; | ||
|
||
extern int write_ethernet_args(int fd, struct ethernet_args *args); | ||
|
||
/* Server -> Client: details of a vif */ | ||
struct vif_info { | ||
uint16_t mtu; | ||
uint16_t max_packet_size; | ||
uint8_t mac[6]; | ||
} __attribute__((packed)); | ||
|
||
/* Server -> Client: disconnect w/reason */ | ||
struct disconnect_reason { | ||
uint8_t len; | ||
char msg[256]; | ||
} __attribute__((packed)); | ||
|
||
struct msg_response { | ||
uint8_t response_type; | ||
union { | ||
struct vif_info vif; | ||
struct disconnect_reason disconnect; | ||
}; | ||
} __attribute__((packed)); | ||
|
||
extern int read_vif_response(int fd, struct vif_info *vif); | ||
|
||
extern char expected_hello[5]; | ||
extern char expected_hello_old[5]; | ||
|
||
extern int really_read(int fd, uint8_t *buffer, size_t total); | ||
extern int really_write(int fd, uint8_t *buffer, size_t total); | ||
|
||
#endif /* _VMNET_PROTOCOL_H_ */ |