Changeset 66ec63a in mainline for uspace/srv/net/dhcp/dhcp.c


Ignore:
Timestamp:
2013-09-23T21:58:03Z (11 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
b417559
Parents:
bd88bee
Message:

Restructure DHCP for event-based reception and multiple instances.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/dhcp/dhcp.c

    rbd88bee r66ec63a  
    3535 */
    3636
     37#include <adt/list.h>
    3738#include <bitops.h>
    3839#include <inet/addr.h>
     
    4950#include "dhcp.h"
    5051#include "dhcp_std.h"
    51 
    52 #define NAME "dhcp"
     52#include "transport.h"
    5353
    5454#define MAX_MSG_SIZE 1024
    55 
    56 static int transport_fd = -1;
    57 static inet_link_info_t link_info;
    5855static uint8_t msgbuf[MAX_MSG_SIZE];
     56
     57static list_t dhcp_links;
    5958
    6059typedef struct {
     
    7170} dhcp_offer_t;
    7271
     72typedef struct {
     73        link_t links;
     74        service_id_t link_id;
     75        inet_link_info_t link_info;
     76        dhcp_transport_t dt;
     77} dhcp_link_t;
     78
     79static void dhcpsrv_recv(void *, void *, size_t);
     80
    7381/** Decode subnet mask into subnet prefix length. */
    7482static int subnet_mask_decode(uint32_t mask, int *bits)
     
    103111}
    104112
    105 static int dhcp_send(void *msg, size_t size)
    106 {
    107         struct sockaddr_in addr;
    108         int rc;
    109 
    110         addr.sin_family = AF_INET;
    111         addr.sin_port = htons(dhcp_server_port);
    112         addr.sin_addr.s_addr = htonl(addr32_broadcast_all_hosts);
    113 
    114         rc = sendto(transport_fd, msg, size, 0,
    115             (struct sockaddr *)&addr, sizeof(addr));
    116         if (rc != EOK) {
    117                 log_msg(LOG_DEFAULT, LVL_ERROR, "Sending failed");
    118                 return rc;
    119         }
    120 
    121         return EOK;
    122 }
    123 
    124 static int dhcp_send_discover(void)
     113static int dhcp_send_discover(dhcp_link_t *dlink)
    125114{
    126115        dhcp_hdr_t *hdr = (dhcp_hdr_t *)msgbuf;
     
    134123        hdr->flags = flag_broadcast;
    135124
    136         addr48(link_info.mac_addr, hdr->chaddr);
     125        addr48(dlink->link_info.mac_addr, hdr->chaddr);
    137126        hdr->opt_magic = host2uint32_t_be(dhcp_opt_magic);
    138127
     
    142131        opt[3] = opt_end;
    143132
    144         return dhcp_send(msgbuf, sizeof(dhcp_hdr_t) + 4);
    145 }
    146 
    147 static int dhcp_recv_msg(void **rmsg, size_t *rsize)
    148 {
    149         struct sockaddr_in src_addr;
    150         socklen_t src_addr_size;
    151         size_t recv_size;
    152         int rc;
    153 
    154         src_addr_size = sizeof(src_addr);
    155         rc = recvfrom(transport_fd, msgbuf, MAX_MSG_SIZE, 0,
    156             (struct sockaddr *)&src_addr, &src_addr_size);
    157         if (rc < 0) {
    158                 log_msg(LOG_DEFAULT, LVL_ERROR, "recvfrom failed (%d)", rc);
    159                 return rc;
    160         }
    161 
    162         recv_size = (size_t)rc;
    163         *rmsg = msgbuf;
    164         *rsize = recv_size;
    165 
    166         return EOK;
    167 }
    168 
    169 static int dhcp_send_request(dhcp_offer_t *offer)
     133        return dhcp_send(&dlink->dt, msgbuf, sizeof(dhcp_hdr_t) + 4);
     134}
     135
     136static int dhcp_send_request(dhcp_link_t *dlink, dhcp_offer_t *offer)
    170137{
    171138        dhcp_hdr_t *hdr = (dhcp_hdr_t *)msgbuf;
     
    180147        hdr->flags = flag_broadcast;
    181148        hdr->ciaddr = host2uint32_t_be(offer->oaddr.addr);
    182         addr48(link_info.mac_addr, hdr->chaddr);
     149        addr48(dlink->link_info.mac_addr, hdr->chaddr);
    183150        hdr->opt_magic = host2uint32_t_be(dhcp_opt_magic);
    184151
     
    205172        opt[i++] = opt_end;
    206173
    207         return dhcp_send(msgbuf, sizeof(dhcp_hdr_t) + i);
    208 }
    209 
    210 static int dhcp_recv_reply(void *msg, size_t size, dhcp_offer_t *offer)
     174        return dhcp_send(&dlink->dt, msgbuf, sizeof(dhcp_hdr_t) + i);
     175}
     176
     177static int dhcp_parse_reply(void *msg, size_t size, dhcp_offer_t *offer)
    211178{
    212179        dhcp_hdr_t *hdr = (dhcp_hdr_t *)msg;
     
    390357                rc = dnsr_set_srvaddr(&offer->dns_server);
    391358                if (rc != EOK) {
    392                         log_msg(LOG_DEFAULT, LVL_ERROR, "%s: Error setting "
    393                             "nameserver address (%d))", NAME, rc);
     359                        log_msg(LOG_DEFAULT, LVL_ERROR, "Error setting "
     360                            "nameserver address (%d))", rc);
    394361                        return rc;
    395362                }
     
    401368int dhcpsrv_link_add(service_id_t link_id)
    402369{
    403         int fd;
    404         struct sockaddr_in laddr;
    405         void *msg;
    406         size_t msg_size;
    407         dhcp_offer_t offer;
     370        dhcp_link_t *dlink;
    408371        int rc;
    409372
    410373        log_msg(LOG_DEFAULT, LVL_DEBUG, "dhcpsrv_link_add(%zu)", link_id);
    411374
     375        dlink = calloc(1, sizeof(dhcp_link_t));
     376        if (dlink == NULL)
     377                return ENOMEM;
     378
     379        dlink->link_id = link_id;
     380
    412381        /* Get link hardware address */
    413         rc = inetcfg_link_get(link_id, &link_info);
     382        rc = inetcfg_link_get(link_id, &dlink->link_info);
    414383        if (rc != EOK) {
    415384                log_msg(LOG_DEFAULT, LVL_ERROR, "Error getting properties "
    416385                    "for link %zu.", link_id);
    417                 return EIO;
    418         }
    419 
    420         laddr.sin_family = AF_INET;
    421         laddr.sin_port = htons(dhcp_client_port);
    422         laddr.sin_addr.s_addr = INADDR_ANY;
    423 
    424         fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
    425         if (fd < 0)
    426                 return EIO;
    427 
    428         log_msg(LOG_DEFAULT, LVL_DEBUG, "Bind socket.");
    429         rc = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr));
    430         if (rc != EOK)
    431                 return EIO;
    432 
    433         log_msg(LOG_DEFAULT, LVL_DEBUG, "Set socket options");
    434         rc = setsockopt(fd, SOL_SOCKET, SO_IPLINK, &link_id, sizeof(link_id));
    435         if (rc != EOK)
    436                 return EIO;
    437 
    438         transport_fd = fd;
     386                rc = EIO;
     387                goto error;
     388        }
     389
     390        rc = dhcp_transport_init(&dlink->dt, link_id, dhcpsrv_recv, dlink);
     391        if (rc != EOK) {
     392                log_msg(LOG_DEFAULT, LVL_ERROR, "Error initializing DHCP "
     393                    "transport for link %s.", dlink->link_info.name);
     394                rc = EIO;
     395                goto error;
     396        }
    439397
    440398        log_msg(LOG_DEFAULT, LVL_DEBUG, "Send DHCPDISCOVER");
    441         rc = dhcp_send_discover();
    442         if (rc != EOK)
    443                 return EIO;
    444 
    445         rc = dhcp_recv_msg(&msg, &msg_size);
    446         if (rc != EOK)
    447                 return EIO;
    448 
    449         log_msg(LOG_DEFAULT, LVL_DEBUG, "Received %zu bytes", msg_size);
    450 
    451         rc = dhcp_recv_reply(msg, msg_size, &offer);
    452         if (rc != EOK)
    453                 return EIO;
    454 
    455         rc = dhcp_send_request(&offer);
    456         if (rc != EOK)
    457                 return EIO;
    458 
    459         rc = dhcp_recv_msg(&msg, &msg_size);
    460         if (rc != EOK)
    461                 return EIO;
    462 
    463         log_msg(LOG_DEFAULT, LVL_DEBUG, "Received %zu bytes", msg_size);
    464 
    465         rc = dhcp_recv_reply(msg, msg_size, &offer);
    466         if (rc != EOK)
    467                 return EIO;
    468 
    469         rc = dhcp_cfg_create(link_id, &offer);
    470         if (rc != EOK)
    471                 return EIO;
    472 
    473         closesocket(fd);
     399        rc = dhcp_send_discover(dlink);
     400        if (rc != EOK) {
     401                rc = EIO;
     402                goto error;
     403        }
     404
     405        if (0) list_append(&dlink->links, &dhcp_links);
     406
    474407        return EOK;
     408error:
     409        free(dlink);
     410        return rc;
    475411}
    476412
     
    480416}
    481417
     418static void dhcpsrv_recv(void *arg, void *msg, size_t size)
     419{
     420        dhcp_link_t *dlink = (dhcp_link_t *)arg;
     421        dhcp_offer_t offer;
     422        int rc;
     423
     424        log_msg(LOG_DEFAULT, LVL_DEBUG, "dhcpsrv_recv() %zu bytes", size);
     425
     426        rc = dhcp_parse_reply(msg, size, &offer);
     427        if (rc != EOK) {
     428                log_msg(LOG_DEFAULT, LVL_DEBUG, "Error parsing reply");
     429                return;
     430        }
     431
     432        if (offer.msg_type == msg_dhcpoffer) {
     433                rc = dhcp_send_request(dlink, &offer);
     434                if (rc != EOK) {
     435                        log_msg(LOG_DEFAULT, LVL_DEBUG, "Error sending request.");
     436                        return;
     437                }
     438        }
     439
     440        if (offer.msg_type == msg_dhcpack) {
     441                rc = dhcp_cfg_create(dlink->link_id, &offer);
     442                if (rc != EOK) {
     443                        log_msg(LOG_DEFAULT, LVL_DEBUG, "Error creating configuration.");
     444                        return;
     445                }
     446        }
     447}
    482448
    483449/** @}
Note: See TracChangeset for help on using the changeset viewer.