File: control.c

package info (click to toggle)
l2tpns 2.1.21-1.1
  • links: PTS
  • area: main
  • in suites: lenny, squeeze, wheezy
  • size: 820 kB
  • ctags: 1,621
  • sloc: ansic: 16,737; makefile: 160; sh: 142; perl: 139
file content (163 lines) | stat: -rw-r--r-- 3,374 bytes parent folder | download | duplicates (2)
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
157
158
159
160
161
162
163
// L2TPNS: control

char const *cvs_id_control = "$Id: control.c,v 1.5 2005/07/31 10:04:10 bodea Exp $";

#include <string.h>
#include "l2tpns.h"
#include "control.h"

int pack_control(uint8_t *data, int len, uint8_t type, int argc, char *argv[])
{
    struct nsctl_packet pkt;
    struct nsctl_args arg;
    char *p = pkt.argv;
    int sz = (p - (char *) &pkt);

    if (len > sizeof(pkt))
    	len = sizeof(pkt);

    if (argc > 0xff)
    	argc = 0xff; // paranoia

    pkt.magic = ntohs(NSCTL_MAGIC);
    pkt.type = type;
    pkt.argc = argc;

    while (argc-- > 0)
    {
	char *a = *argv++;
	int s = strlen(a);

	if (s > sizeof(arg.value))
		s = sizeof(arg.value); // silently truncate

	arg.len = s;
	s += sizeof(arg.len);

	if (sz + s > len)
	    return -1; // overflow

	if (arg.len)
	    memcpy(arg.value, a, arg.len);

	memcpy(p, &arg, s);
	sz += s;
	p += s;
    }

    /*
     * terminate:  this is both a sanity check and additionally
     * ensures that there's a spare byte in the packet to null
     * terminate the last argument when unpacking (see unpack_control)
     */
    if (sz + sizeof(arg.len) > len)
    	return -1; // overflow

    arg.len = 0xff;
    memcpy(p, &arg.len, sizeof(arg.len));

    sz += sizeof(arg.len);
    memcpy(data, &pkt, sz);

    return sz;
}

int unpack_control(struct nsctl *control, uint8_t *data, int len)
{
    struct nsctl_packet pkt;
    char *p = pkt.argv;
    int sz = (p - (char *) &pkt);
    int i;

    if (len < sz)
    	return NSCTL_ERR_SHORT;

    if (len > sizeof(pkt))
    	return NSCTL_ERR_LONG;

    memcpy(&pkt, data, len);
    if (ntohs(pkt.magic) != NSCTL_MAGIC)
    	return NSCTL_ERR_MAGIC;

    switch (pkt.type)
    {
    case NSCTL_REQ_LOAD:
    case NSCTL_REQ_UNLOAD:
    case NSCTL_REQ_HELP:
    case NSCTL_REQ_CONTROL:
    case NSCTL_RES_OK:
    case NSCTL_RES_ERR:
	control->type = pkt.type;
	break;

    default:
	return NSCTL_ERR_TYPE;
    }

    control->argc = pkt.argc;
    for (i = 0; i <= control->argc; i++)
    {
	unsigned s;

	if (len < sz + 1)
	    return NSCTL_ERR_SHORT;

	s = (uint8_t) *p;
	*p++ = 0; // null terminate previous arg
	sz++;

	if (i < control->argc)
	{
	    if (len < sz + s)
		return NSCTL_ERR_SHORT;

	    control->argv[i] = p;
	    p += s;
	    sz += s;
	}
	else
	{
	    /* check for terminator */
	    if (s != 0xff)
	    	return NSCTL_ERR_SHORT;
	}
    }

    if (sz != len)
    	return NSCTL_ERR_LONG; // trailing cr*p

    return control->type;
}

void dump_control(struct nsctl *control, FILE *stream)
{
    char *type = "*unknown*";

    if (!stream)
    	stream = stdout;

    switch (control->type)
    {
    case NSCTL_REQ_LOAD:	type = "NSCTL_REQ_LOAD";	break;
    case NSCTL_REQ_UNLOAD:	type = "NSCTL_REQ_UNLOAD";	break;
    case NSCTL_REQ_HELP:	type = "NSCTL_REQ_HELP";	break;
    case NSCTL_REQ_CONTROL:	type = "NSCTL_REQ_CONTROL";	break;
    case NSCTL_RES_OK:		type = "NSCTL_RES_OK";		break;
    case NSCTL_RES_ERR:		type = "NSCTL_RES_ERR";		break;
    }

    fprintf(stream, "Control packet:\n");
    fprintf(stream, "	Type: %d (%s)\n", (int) control->type, type);
    fprintf(stream, "	Args: %d", (int) control->argc);
    if (control->argc)
    {
	int i;
	fprintf(stream, " (\"");
	for (i = 0; i < control->argc; i++)
	    fprintf(stream, "%s%s", i ? "\", \"" : "", control->argv[i]);

	fprintf(stream, "\")");
    }

    fprintf(stream, "\n\n");
}