1/*
2 * Copyright (c) 2007-12 ETH Zurich.
3 * All rights reserved.
4 *
5 * This file is distributed under the terms in the attached LICENSE file.
6 * If you do not find this file, copies can be found by writing to:
7 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
8 */
9
10#include <barrelfish/barrelfish.h>
11#include <barrelfish/waitset.h>
12
13// to connect with service
14#include <barrelfish/nameservice_client.h>
15#include <barrelfish/net_constants.h>
16
17#include <if/net_ARP_defs.h>
18#include <if/net_ARP_defs.h>
19
20// standard include files
21#include <stdio.h>
22
23// for netif struct
24#include <netif/bfeth.h>
25#include <netif/etharp.h>
26
27// local include files
28#include "idc_barrelfish.h"
29#include "lwip_barrelfish_debug.h"
30
31// *****************************************************************
32//     local states
33// *****************************************************************
34static struct net_ARP_binding *net_ARP_binding;
35static bool net_ARP_service_connected = false;
36static struct netif netif;
37
38/****************************************************************
39* Global states
40*****************************************************************/
41extern struct waitset *lwip_waitset;
42
43// *****************************************************************
44// Dealing with new connections
45// *****************************************************************
46static void net_ARP_bind_cb(void *st, errval_t err, struct net_ARP_binding *b)
47{
48    if (err_is_fail(err)) {
49        DEBUG_ERR(err, "bind failed for net_ARP");
50        abort();
51    }
52    LWIPBF_DEBUG("net_ARP_bind_cb: called\n");
53    net_ARP_binding = b;
54    net_ARP_rpc_client_init(b);
55    net_ARP_service_connected = true;
56    LWIPBF_DEBUG("net_ARP_bind_cb: net_ARP bind successful!\n");
57}
58
59static void init_net_ARP_connection(char *service_name)
60{
61    LWIPBF_DEBUG("init_net_ARP_connection: called\n");
62    assert(service_name != NULL);
63    LWIPBF_DEBUG("init_net_ARP_connection: connecting to [%s]\n", service_name);
64
65    errval_t err;
66    iref_t iref;
67
68    LWIPBF_DEBUG("init_net_ARP_connection: resolving driver %s\n", service_name);
69
70    err = nameservice_blocking_lookup(service_name, &iref);
71    if (err_is_fail(err)) {
72        DEBUG_ERR(err, "lwip: could not connect to the net_ARP driver.\n"
73                  "Terminating.\n");
74        abort();
75    }
76    assert(iref != 0);
77
78    LWIPBF_DEBUG("init_net_ARP_connection: connecting\n");
79
80    err = net_ARP_bind(iref, net_ARP_bind_cb, NULL, lwip_waitset,
81                    IDC_BIND_FLAGS_DEFAULT);
82    if (!err_is_ok(err)) {
83        printf("net_ARP_bind_cb failed in init\n");
84        abort();
85    }
86
87    LWIPBF_DEBUG("init_net_ARP_connection: terminated\n");
88}
89
90
91// Connects to the port manager service
92// Blocking call: returns only when connection is done
93// In case of error, it will panic!!
94void idc_connect_ARP_lookup_service(char *service_name)
95{
96    LWIPBF_DEBUG("idc_c_ARP_lookup_srv: trying to [%s]\n", service_name);
97
98    /* FIXME: decide if this is the best place to connect with net_ARP */
99    init_net_ARP_connection(service_name);
100
101    // XXX: dispatch on default waitset until bound
102    struct waitset *dws = get_default_waitset();
103
104    while (!net_ARP_service_connected) {
105        errval_t err = event_dispatch(dws);
106
107        if (err_is_fail(err)) {
108            USER_PANIC_ERR(err, "in event_dispatch while binding ARP_service");
109        }
110    }
111    LWIPBF_DEBUG("idc_c_ARP_lookup_srv: success [%s]\n", service_name);
112}
113
114
115// ************************************************************************
116//                 ARP lookup interface function
117// ************************************************************************
118
119
120void idc_get_ip_from_ARP_lookup(void)
121{
122    /*
123    if (is_owner) {
124        assert(!"owner of lwip should never ask for ip through API\n");
125        abort();
126    }
127    */
128    LWIPBF_DEBUG("On the way of getting IP via ARP lookup\n");
129
130    errval_t err;
131    errval_t remote_err;
132    struct ip_addr ip, gw, nm;
133    uint32_t iface = 0;
134
135    err = net_ARP_binding->rpc_tx_vtbl.ip_info(net_ARP_binding, iface, &remote_err,
136            &ip.addr, &gw.addr, &nm.addr);
137    if (err_is_fail(err)) {
138        USER_PANIC_ERR(err, "error in making ip_info call");
139    }
140
141    if (err_is_fail(remote_err)) {
142        USER_PANIC_ERR(remote_err, "error in getting ip_info");
143    }
144
145    LWIPBF_DEBUG("got answer, now setting up things\n");
146    netif_add(&netif, &ip, &nm, &gw, NULL, bfeth_init, ethernet_input);
147    netif_set_default(&netif);
148    netif_set_up(&netif);
149
150    LWIPBF_DEBUG("client: owner has the IP address %d.%d.%d.%d\n",
151                 ip4_addr1(&netif.ip_addr), ip4_addr2(&netif.ip_addr),
152                 ip4_addr3(&netif.ip_addr), ip4_addr4(&netif.ip_addr));
153}
154
155uint64_t idc_ARP_lookup(uint32_t ip)
156{
157    /*
158    if (is_owner) {
159        assert(!"ARP server should never use this API for ARP lookup\n");
160        abort();
161    }
162    */
163    LWIPBF_DEBUG("idc_ARP_lookup: On the way of ARP lookup\n");
164
165    errval_t err;
166    errval_t remote_err;
167    uint32_t iface = 0;
168    bool force = false;
169    uint64_t mac = 0;
170
171    err = net_ARP_binding->rpc_tx_vtbl.ARP_lookup(net_ARP_binding, ip, iface, force,
172            &remote_err, &mac);
173    if (err_is_fail(err)) {
174        USER_PANIC_ERR(err, "error in making ARP_lookup call");
175    }
176
177    if (err_is_fail(remote_err)) {
178        USER_PANIC_ERR(remote_err, "error in ARP lookup process");
179    }
180    assert(mac != 0);
181
182    LWIPBF_DEBUG("idc_ARP_lookup: got answer\n");
183    return mac;
184} // end function: idc_ARP_lookup
185