summaryrefslogtreecommitdiff
path: root/accel-pppd/ppp/lcp_opt_magic.c
blob: 52ed26eb58fa8bb0a4ecd47b597933107b61ca58 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>

#include "ppp.h"
#include "ppp_lcp.h"
#include "log.h"

#include "memdebug.h"

static struct lcp_option_t *magic_init(struct ppp_lcp_t *lcp);
static void magic_free(struct ppp_lcp_t *lcp, struct lcp_option_t *opt);
static int magic_send_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr);
static int magic_send_conf_nak(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr);
static int magic_recv_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr);
static int magic_recv_conf_rej(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr);
static int magic_recv_conf_nak(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr);
static void magic_print(void (*print)(const char *fmt, ...), struct lcp_option_t*, uint8_t *ptr);

struct magic_option_t
{
	struct lcp_option_t opt;
	int magic;
};

static struct lcp_option_handler_t magic_opt_hnd=
{
	.init = magic_init,
	.send_conf_req = magic_send_conf_req,
	.send_conf_nak = magic_send_conf_nak,
	.recv_conf_req = magic_recv_conf_req,
	.recv_conf_rej = magic_recv_conf_rej,
	.recv_conf_nak = magic_recv_conf_nak,
	.free = magic_free,
	.print = magic_print,
};

static int nzmagic(int old)
{
	int magic;

	do {
		magic = random();
	} while (magic == old || !magic);

	return magic;
}

static struct lcp_option_t *magic_init(struct ppp_lcp_t *lcp)
{
	struct magic_option_t *magic_opt = _malloc(sizeof(*magic_opt));

	memset(magic_opt, 0, sizeof(*magic_opt));
	magic_opt->magic = nzmagic(0);
	magic_opt->opt.id = CI_MAGIC;
	magic_opt->opt.len = 6;

	lcp->magic = magic_opt->magic;

	return &magic_opt->opt;
}

static void magic_free(struct ppp_lcp_t *lcp, struct lcp_option_t *opt)
{
	struct magic_option_t *magic_opt = container_of(opt,typeof(*magic_opt),opt);

	_free(magic_opt);
}

static int magic_send_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr)
{
	struct magic_option_t *magic_opt = container_of(opt, typeof(*magic_opt), opt);
	struct lcp_opt32_t *opt32 = (struct lcp_opt32_t *)ptr;

	if (!magic_opt->magic)
		return 0;

	opt32->hdr.id = CI_MAGIC;
	opt32->hdr.len = 6;
	opt32->val = htonl(magic_opt->magic);
	return 6;
}

static int magic_send_conf_nak(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr)
{
	struct magic_option_t *magic_opt = container_of(opt, typeof(*magic_opt), opt);
	struct lcp_opt32_t *opt32 = (struct lcp_opt32_t *)ptr;

	opt32->hdr.id = CI_MAGIC;
	opt32->hdr.len = 6;
	opt32->val = htonl(nzmagic(magic_opt->magic));
	return 6;
}

static int magic_recv_conf_req(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr)
{
	struct magic_option_t *magic_opt = container_of(opt, typeof(*magic_opt), opt);
	struct lcp_opt32_t *opt32 = (struct lcp_opt32_t *)ptr;

	/*if (!ptr)
		return LCP_OPT_NAK;*/

	if (opt32->hdr.len != 6)
		return LCP_OPT_REJ;

	if (magic_opt->magic && magic_opt->magic == ntohl(opt32->val))
		return LCP_OPT_NAK;

	return LCP_OPT_ACK;
}

static int magic_recv_conf_rej(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr)
{
	struct magic_option_t *magic_opt = container_of(opt, typeof(*magic_opt), opt);

	magic_opt->magic = 0;
	lcp->magic = 0;

	return 0;
}

static int magic_recv_conf_nak(struct ppp_lcp_t *lcp, struct lcp_option_t *opt, uint8_t *ptr)
{
	struct magic_option_t *magic_opt = container_of(opt, typeof(*magic_opt), opt);
	struct lcp_opt32_t *opt32 = (struct lcp_opt32_t *)ptr;

	if (opt32->hdr.len != 6)
		return -1;

	/* Loop-back detected */
	if (magic_opt->magic && magic_opt->magic == ntohl(opt32->val))
		return -1;

	magic_opt->magic = ntohl(opt32->val) ? : nzmagic(magic_opt->magic);
	lcp->magic = magic_opt->magic;

	return 0;
}

static void magic_print(void (*print)(const char *fmt, ...), struct lcp_option_t *opt, uint8_t *ptr)
{
	struct magic_option_t *magic_opt = container_of(opt, typeof(*magic_opt), opt);
	struct lcp_opt32_t *opt32 = (struct lcp_opt32_t *)ptr;

	if (ptr)
		print("<magic %08x>", ntohl(opt32->val));
	else
		print("<magic %08x>", magic_opt->magic);
}

static void magic_opt_init()
{
	lcp_option_register(&magic_opt_hnd);
}

DEFINE_INIT(4, magic_opt_init);