~yolanda.robla/ubuntu/saucy/freeradius/dep-8-tests

« back to all changes in this revision

Viewing changes to src/main/dhcpd.c

  • Committer: Bazaar Package Importer
  • Author(s): Josip Rodin
  • Date: 2009-11-23 03:57:37 UTC
  • mto: This revision was merged to the branch mainline in revision 7.
  • Revision ID: james.westby@ubuntu.com-20091123035737-snauioz5r9tf8sdr
Tags: upstream-2.1.7+dfsg
ImportĀ upstreamĀ versionĀ 2.1.7+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * dhcp.c       DHCP processing.  Done poorly for now.
3
3
 *
4
 
 * Version:     $Id: dhcpd.c,v 1.1 2008/04/20 15:00:06 aland Exp $
 
4
 * Version:     $Id$
5
5
 *
6
6
 *   This program is free software; you can redistribute it and/or modify
7
7
 *   it under the terms of the GNU General Public License as published by
23
23
 
24
24
#ifdef WITH_DHCP
25
25
 
 
26
/*
 
27
 *      Same layout, etc. as listen_socket_t.
 
28
 */
 
29
typedef struct dhcp_socket_t {
 
30
        /*
 
31
         *      For normal sockets.
 
32
         */
 
33
        fr_ipaddr_t     ipaddr;
 
34
        int             port;
 
35
#ifdef SO_BINDTODEVICE
 
36
        const char      *interface;
 
37
#endif
 
38
        int             suppress_responses;
 
39
        RADCLIENT       dhcp_client;
 
40
} dhcp_socket_t;
 
41
 
26
42
static int dhcp_process(REQUEST *request)
27
43
{
28
44
        int rcode;
40
56
        }
41
57
 
42
58
        /*
43
 
         *      Look for Relay attribute, and forward it if so...
 
59
         *      Look for Relay attribute, and forward it if necessary.
44
60
         */
45
 
 
46
 
        switch (rcode) {
 
61
        vp = pairfind(request->config_items, DHCP2ATTR(270));
 
62
        if (vp) {
 
63
                VALUE_PAIR *giaddr;
 
64
                RADIUS_PACKET relayed;
 
65
                
 
66
                request->reply->code = 0; /* don't reply to the client */
 
67
 
 
68
                /*
 
69
                 *      Find the original giaddr.
 
70
                 *      FIXME: Maybe look in the original packet?
 
71
                 *
 
72
                 *      It's invalid to have giaddr=0 AND a relay option
 
73
                 */
 
74
                giaddr = pairfind(request->packet->vps, 266);
 
75
                if (giaddr && (giaddr->vp_ipaddr == htonl(INADDR_ANY))) {
 
76
                        if (pairfind(request->packet->vps, DHCP2ATTR(82))) {
 
77
                                RDEBUG("DHCP: Received packet with giaddr = 0 and containing relay option: Discarding packet");
 
78
                                return 1;
 
79
                        }
 
80
 
 
81
                        /*
 
82
                         *      FIXME: Add cache by XID.
 
83
                         */
 
84
                        RDEBUG("DHCP: Cannot yet relay packets with giaddr = 0");
 
85
                        return 1;
 
86
                }
 
87
 
 
88
                if (request->packet->data[3] > 10) {
 
89
                        RDEBUG("DHCP: Number of hops is greater than 10: not relaying");
 
90
                        return 1;
 
91
                }
 
92
 
 
93
                /*
 
94
                 *      Forward it VERBATIM to the next server, rather
 
95
                 *      than to the client.
 
96
                 */
 
97
                memcpy(&relayed, request->packet, sizeof(relayed));
 
98
 
 
99
                relayed.dst_ipaddr.af = AF_INET;
 
100
                relayed.dst_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
 
101
                relayed.dst_port = request->packet->dst_port;
 
102
 
 
103
                relayed.src_ipaddr = request->packet->dst_ipaddr;
 
104
                relayed.src_port = request->packet->dst_port;
 
105
 
 
106
                relayed.data = rad_malloc(relayed.data_len);
 
107
                memcpy(relayed.data, request->packet->data, request->packet->data_len);
 
108
                relayed.vps = NULL;
 
109
 
 
110
                /*
 
111
                 *      The only field that changes is the number of hops
 
112
                 */
 
113
                relayed.data[3]++; /* number of hops */
 
114
                
 
115
                /*
 
116
                 *      Forward the relayed packet VERBATIM, don't
 
117
                 *      respond to the client, and forget completely
 
118
                 *      about this request.
 
119
                 */
 
120
                fr_dhcp_send(&relayed);
 
121
                free(relayed.data);
 
122
                return 1;
 
123
        }
 
124
 
 
125
        vp = pairfind(request->reply->vps, DHCP2ATTR(53)); /* DHCP-Message-Type */
 
126
        if (vp) {
 
127
                request->reply->code = vp->vp_integer;
 
128
                if ((request->reply->code != 0) &&
 
129
                    (request->reply->code < PW_DHCP_OFFSET)) {
 
130
                        request->reply->code += PW_DHCP_OFFSET;
 
131
                }
 
132
        }
 
133
        else switch (rcode) {
47
134
        case RLM_MODULE_OK:
48
135
        case RLM_MODULE_UPDATED:
49
 
                if (request->packet->code == (PW_DHCP_DISCOVER)) {
 
136
                if (request->packet->code == PW_DHCP_DISCOVER) {
50
137
                        request->reply->code = PW_DHCP_OFFER;
51
138
                        break;
52
139
 
62
149
        case RLM_MODULE_FAIL:
63
150
        case RLM_MODULE_INVALID:
64
151
        case RLM_MODULE_NOOP:
65
 
                request->reply->code = PW_DHCP_NAK;
66
 
                break;
67
 
 
68
152
        case RLM_MODULE_NOTFOUND:
69
 
                request->reply->code = PW_DHCP_DECLINE;
 
153
                request->reply->code = PW_DHCP_NAK;
70
154
                break;
71
155
 
72
156
        case RLM_MODULE_HANDLED:
73
 
                request->reply->code = PW_DHCP_NAK;
74
157
                break;
75
158
        }
76
159
 
81
164
{
82
165
        int rcode;
83
166
        int on = 1;
84
 
        listen_socket_t *sock;
 
167
        dhcp_socket_t *sock;
 
168
        RADCLIENT *client;
 
169
        CONF_PAIR *cp;
85
170
 
86
171
        rcode = common_socket_parse(cs, this);
87
172
        if (rcode != 0) return rcode;
103
188
                return -1;
104
189
        }
105
190
 
 
191
        /*
 
192
         *      Undocumented extension for testing without
 
193
         *      destroying your network!
 
194
         */
 
195
        sock->suppress_responses = FALSE;
 
196
        cp = cf_pair_find(cs, "suppress_responses");
 
197
        if (cp) {
 
198
                const char *value;
 
199
 
 
200
                value = cf_pair_value(cp);
 
201
 
 
202
                if (value && (strcmp(value, "yes") == 0)) {
 
203
                        sock->suppress_responses = TRUE;
 
204
                }
 
205
        }
 
206
 
 
207
        /*
 
208
         *      Initialize the fake client.
 
209
         */
 
210
        client = &sock->dhcp_client;
 
211
        memset(client, 0, sizeof(*client));
 
212
        client->ipaddr.af = AF_INET;
 
213
        client->ipaddr.ipaddr.ip4addr.s_addr = INADDR_NONE;
 
214
        client->prefix = 0;
 
215
        client->longname = client->shortname = "dhcp";
 
216
        client->secret = client->shortname;
 
217
        client->nastype = strdup("none");
 
218
 
106
219
        return 0;
107
220
}
108
221
 
117
230
                            RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
118
231
{
119
232
        RADIUS_PACKET   *packet;
120
 
        RADCLIENT       *client;
 
233
        dhcp_socket_t   *sock;
121
234
 
122
235
        packet = fr_dhcp_recv(listener->fd);
123
236
        if (!packet) {
124
 
                radlog(L_ERR, "%s", librad_errstr);
125
 
                return 0;
126
 
        }
127
 
 
128
 
        if ((client = client_listener_find(listener,
129
 
                                           &packet->src_ipaddr)) == NULL) {
130
 
                char buffer[256];
131
 
                radlog(L_ERR, "Ignoring request from unknown client %s port %d",
132
 
                       inet_ntop(packet->src_ipaddr.af,
133
 
                                 &packet->src_ipaddr.ipaddr,
134
 
                                 buffer, sizeof(buffer)),
135
 
                       packet->src_port);
136
 
                rad_free(&packet);
137
 
                return 0;
138
 
        }
139
 
 
140
 
        if (!received_request(listener, packet, prequest, client)) {
 
237
                radlog(L_ERR, "%s", fr_strerror());
 
238
                return 0;
 
239
        }
 
240
 
 
241
        sock = listener->data;
 
242
        if (!received_request(listener, packet, prequest, &sock->dhcp_client)) {
141
243
                rad_free(&packet);
142
244
                return 0;
143
245
        }
153
255
 */
154
256
static int dhcp_socket_send(rad_listen_t *listener, REQUEST *request)
155
257
{
 
258
        dhcp_socket_t   *sock;
 
259
 
156
260
        rad_assert(request->listener == listener);
157
261
        rad_assert(listener->send == dhcp_socket_send);
158
262
 
162
266
                return -1;
163
267
        }
164
268
 
 
269
        sock = listener->data;
 
270
        if (sock->suppress_responses) return 0;
 
271
 
 
272
        /*
 
273
         *      Don't send anything
 
274
         */
165
275
        return fr_dhcp_send(request->reply);
166
276
}
167
277