source: mainline/uspace/srv/net/dhcp/transport.c@ 4d11204

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 4d11204 was e3811c9, checked in by Jiri Svoboda <jiri@…>, 10 years ago

Work around issue with simultaneous DHCP sessions (thx Jan Buchar).

  • Property mode set to 100644
File size: 4.5 KB
Line 
1/*
2 * Copyright (c) 2013 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup dhcp
30 * @{
31 */
32/**
33 * @file
34 * @brief DHCP client
35 */
36
37#include <bitops.h>
38#include <inet/addr.h>
39#include <inet/dnsr.h>
40#include <inet/inetcfg.h>
41#include <io/log.h>
42#include <loc.h>
43#include <net/in.h>
44#include <net/inet.h>
45#include <net/socket.h>
46#include <stdio.h>
47#include <stdlib.h>
48
49#include "dhcp.h"
50#include "dhcp_std.h"
51#include "transport.h"
52
53#define MAX_MSG_SIZE 1024
54static uint8_t msgbuf[MAX_MSG_SIZE];
55
56typedef struct {
57 /** Message type */
58 enum dhcp_msg_type msg_type;
59 /** Offered address */
60 inet_naddr_t oaddr;
61 /** Server address */
62 inet_addr_t srv_addr;
63 /** Router address */
64 inet_addr_t router;
65 /** DNS server */
66 inet_addr_t dns_server;
67} dhcp_offer_t;
68
69static int dhcp_recv_fibril(void *);
70
71int dhcp_send(dhcp_transport_t *dt, void *msg, size_t size)
72{
73 struct sockaddr_in addr;
74 int rc;
75
76 addr.sin_family = AF_INET;
77 addr.sin_port = htons(dhcp_server_port);
78 addr.sin_addr.s_addr = htonl(addr32_broadcast_all_hosts);
79
80 rc = sendto(dt->fd, msg, size, 0,
81 (struct sockaddr *)&addr, sizeof(addr));
82 if (rc != EOK) {
83 log_msg(LOG_DEFAULT, LVL_ERROR, "Sending failed");
84 return rc;
85 }
86
87 return EOK;
88}
89
90static int dhcp_recv_msg(dhcp_transport_t *dt, void **rmsg, size_t *rsize)
91{
92 struct sockaddr_in src_addr;
93 socklen_t src_addr_size;
94 size_t recv_size;
95 int rc;
96
97 if (dt->fd < 0) {
98 /* Terminated */
99 return EIO;
100 }
101
102 src_addr_size = sizeof(src_addr);
103 rc = recvfrom(dt->fd, msgbuf, MAX_MSG_SIZE, 0,
104 (struct sockaddr *)&src_addr, &src_addr_size);
105 if (rc < 0) {
106 log_msg(LOG_DEFAULT, LVL_ERROR, "recvfrom failed (%d)", rc);
107 return rc;
108 }
109
110 recv_size = (size_t)rc;
111 *rmsg = msgbuf;
112 *rsize = recv_size;
113
114 return EOK;
115}
116
117int dhcp_transport_init(dhcp_transport_t *dt, service_id_t link_id,
118 dhcp_recv_cb_t recv_cb, void *arg)
119{
120 int fd;
121 struct sockaddr_in laddr;
122 int fid;
123 int rc;
124
125 log_msg(LOG_DEFAULT, LVL_DEBUG, "dhcptransport_init()");
126
127 laddr.sin_family = AF_INET;
128 laddr.sin_port = htons(dhcp_client_port);
129 laddr.sin_addr.s_addr = INADDR_ANY;
130
131 fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
132 if (fd < 0) {
133 rc = EIO;
134 goto error;
135 }
136
137 log_msg(LOG_DEFAULT, LVL_DEBUG, "Bind socket.");
138 rc = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr));
139 if (rc != EOK) {
140 rc = EIO;
141 goto error;
142 }
143
144 log_msg(LOG_DEFAULT, LVL_DEBUG, "Set socket options");
145 rc = setsockopt(fd, SOL_SOCKET, SO_IPLINK, &link_id, sizeof(link_id));
146 if (rc != EOK) {
147 rc = EIO;
148 goto error;
149 }
150
151 dt->fd = fd;
152 dt->recv_cb = recv_cb;
153 dt->cb_arg = arg;
154
155 fid = fibril_create(dhcp_recv_fibril, dt);
156 if (fid == 0) {
157 rc = ENOMEM;
158 goto error;
159 }
160
161 dt->recv_fid = fid;
162 fibril_add_ready(fid);
163
164 return EOK;
165error:
166 closesocket(fd);
167 return rc;
168}
169
170void dhcp_transport_fini(dhcp_transport_t *dt)
171{
172 closesocket(dt->fd);
173 dt->fd = -1;
174}
175
176static int dhcp_recv_fibril(void *arg)
177{
178 dhcp_transport_t *dt = (dhcp_transport_t *)arg;
179 void *msg;
180 size_t size = (size_t) -1;
181 int rc;
182
183 while (true) {
184 rc = dhcp_recv_msg(dt, &msg, &size);
185 if (rc != EOK)
186 break;
187
188 assert(size != (size_t) -1);
189
190 dt->recv_cb(dt->cb_arg, msg, size);
191 }
192
193 return EOK;
194}
195
196/** @}
197 */
Note: See TracBrowser for help on using the repository browser.