bare-socket.c 2.02 KB
Newer Older
1 2 3 4 5
/*
 * Alessandro Rubini for CERN, 2011 -- public domain
 */

/* Socket interface for bare Linux */
6 7
#include <pptp/pptp.h>
#include <pptp/diag.h>
8 9
#include "bare-linux.h"

10
/* FIXME: which socket we receive and send with? */
11 12
int bare_recv_packet(struct pp_instance *ppi, void *pkt, int len)
{
13
	return sys_recv(NP(ppi)->ch[PP_NP_GEN].fd, pkt, len, 0);
14 15
}

16
int bare_send_packet(struct pp_instance *ppi, void *pkt, int len, int chtype)
17
{
18
	return sys_send(NP(ppi)->ch[chtype].fd, pkt, len, 0);
19 20 21 22
}

int pp_recv_packet(struct pp_instance *ppi, void *pkt, int len)
	__attribute__((alias("bare_recv_packet")));
23
int pp_send_packet(struct pp_instance *ppi, void *pkt, int len, int chtype)
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
	__attribute__((alias("bare_send_packet")));

#define PF_PACKET 17
#define SOCK_RAW 3

/* To open a channel we must bind to an interface and so on */
int bare_open_ch(struct pp_instance *ppi, char *ifname)
{
	int sock, iindex;
	struct bare_ifreq ifr;
	struct bare_sockaddr_ll addr;

	/* open socket */
	sock = sys_socket(PF_PACKET, SOCK_RAW, PP_PROTO_NR);
	if (sock < 0) {
		pp_diag_error(ppi, bare_errno);
		pp_diag_fatal(ppi, "socket()", "");
	}

	/* hw interface information */
	memset(&ifr, 0, sizeof(ifr));
	strcpy(ifr.ifr_ifrn.ifrn_name, ifname);
	if (sys_ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
		pp_diag_error(ppi, bare_errno);
		pp_diag_fatal(ppi, "ioctl(GIFINDEX)", "");
	}

	iindex = ifr.ifr_ifru.index;
	if (sys_ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
		pp_diag_error(ppi, bare_errno);
		pp_diag_fatal(ppi, "ioctl(GIFHWADDR)", "");
	}
56
	memcpy(NP(ppi)->ch[PP_NP_GEN].addr,
57
	       ifr.ifr_ifru.ifru_hwaddr.sa_data, 6);
58
	memcpy(NP(ppi)->ch[PP_NP_EVT].addr,
59
	       ifr.ifr_ifru.ifru_hwaddr.sa_data, 6);
60 61 62 63 64 65 66 67 68 69 70

	/* bind and setsockopt */
	memset(&addr, 0, sizeof(addr));
	addr.sll_family = PF_PACKET;
	addr.sll_protocol = htons(PP_PROTO_NR);
	addr.sll_ifindex = iindex;
	if (sys_bind(sock, (struct bare_sockaddr *)&addr, sizeof(addr)) < 0) {
		pp_diag_error(ppi, bare_errno);
		pp_diag_fatal(ppi, "bind", "");
	}

71 72
	NP(ppi)->ch[PP_NP_GEN].fd = sock;
	NP(ppi)->ch[PP_NP_EVT].fd = sock;
73 74
	return 0;
}