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/nameservice_client.h>
12#include <barrelfish/net_constants.h>
13#include <if/net_ARP_defs.h>
14
15#include <barrelfish/waitset.h>
16
17// standard libraries
18#include <stdio.h>
19#include <string.h>
20
21#include <lwip/init.h>
22#include <netif/etharp.h>
23
24// local includes
25#include "netd_private.h"
26#include <netd/netd_debug.h>
27
28// ***** Special cases ********
29// local ip address (your own ip address) (valid request)
30// broadcast ip address (invalid request)
31// multicast IP address (invalid request)
32//
33//
34//
35
36
37// How can I get my own MAC address
38// Where can I find the code which is looking up local MAC address?
39//    struct eth_addr *srcaddr = (struct eth_addr *) netif->hwaddr;
40//
41//
42//        return etharp_query(netif, ipaddr, q); // q is pbuf
43//        lib/lwip/src/netif/etharp.c
44
45//        find_entry
46//        src/netif/etharp.c
47
48/*****************************************************************
49* Prototypes
50*****************************************************************/
51
52static errval_t get_ip_info(struct net_ARP_binding *cc, uint32_t iface,
53                        errval_t *err, net_ARP_ipv4addr_t *ip,
54                        net_ARP_ipv4addr_t *gw, net_ARP_ipv4addr_t *mask);
55static errval_t ARP_resolve_request(struct net_ARP_binding *cc,
56            ipv4addr_t ip, uint32_t iface, bool force,
57            errval_t *err, uint64_t *mac);
58
59// service mappings
60static struct net_ARP_rpc_rx_vtbl rpc_rx_ARP_vtbl = {
61    .ip_info_call = get_ip_info,
62    .ARP_lookup_call = ARP_resolve_request,
63};
64
65
66/*****************************************************************
67* Dealing with new connections
68*****************************************************************/
69static errval_t connect_ARP_cb(void *st, struct net_ARP_binding *b)
70{
71    errval_t err = SYS_ERR_OK;
72    struct netd_state *state = st;
73    NETD_DEBUG("########### new application came in\n");
74
75    // using the b->st to store session specific data (net_user)
76    struct ARP_user_cl *new_app = malloc(sizeof(struct ARP_user_cl));
77
78    if (new_app == NULL) {
79        NETD_DEBUG("error: malloc failed...\n");
80        err = PORT_ERR_NOT_ENOUGH_MEMORY;
81        return err;
82    }
83
84    memset(new_app, 0, sizeof(struct ARP_user_cl));
85    new_app->state = state;
86    new_app->next = state->registered_user_list;
87    state->registered_user_list = new_app;
88    b->st = (void *) new_app;
89
90    b->rpc_rx_vtbl = rpc_rx_ARP_vtbl;
91    return err;
92} // end function: connect_ARP_cb
93
94
95/*****************************************************************
96* exporting service
97*****************************************************************/
98
99static void export_ARP_cb(void *st, errval_t err, iref_t iref)
100{
101    struct netd_state *state = st;
102
103    if (err_is_fail(err)) {
104        DEBUG_ERR(err, "service[%s] export failed", state->ARP_service_name);
105        abort(); // FIXME: Do I need abort after DEBUG_ERR?
106    }
107
108    NETD_DEBUG("service [%s] exported at iref %u\n", state->ARP_service_name, iref);
109
110    // register this iref with the name service
111    err = nameservice_register(state->ARP_service_name, iref);
112    if (err_is_fail(err)) {
113        DEBUG_ERR(err, "nameservice_register failed for [%s]", state->ARP_service_name);
114        abort(); // FIXME: Do I need abort after DEBUG_ERR?
115    }
116    state->ARP_service_exported = true;
117    NETD_DEBUG("service [%s] export successful!\n", state->ARP_service_name);
118} // end function: export_ARP_cb
119
120
121
122// ************************************************************************
123//                 ARP lookup interface function
124// ************************************************************************
125
126static errval_t get_ip_info(struct net_ARP_binding *cc, uint32_t iface,
127                        errval_t *err, net_ARP_ipv4addr_t *ip,
128                        net_ARP_ipv4addr_t *gw, net_ARP_ipv4addr_t *mask)
129{
130    printf("####### get IP info called ######\n");
131    NETD_DEBUG("get_ip_info: client asking for ip over %"PRIu32"\n", iface);
132    struct ARP_user_cl *app = cc->st;
133    struct netd_state *state = app->state;
134
135    *err = SYS_ERR_OK;
136    *ip = state->netif_ptr->ip_addr.addr;
137    *gw = state->netif_ptr->gw.addr;
138    *mask = state->netif_ptr->netmask.addr;
139    NETD_DEBUG("get_ip_info: terminating\n");
140    return SYS_ERR_OK;
141}
142
143static uint64_t refresh_cache(uint32_t dst_ip_addr)
144{
145    struct ip_addr dst_ip;
146    struct netif *netif;
147
148    dst_ip.addr = dst_ip_addr;
149    netif = ip_route(&dst_ip);
150
151    NETD_DEBUG("refresh_cache: calling etharp_request\n");
152    errval_t r = etharp_request(netif, &dst_ip);
153    assert(err_is_ok(r));
154
155    struct waitset *ws = NULL;
156    ws = get_default_waitset();
157    while (is_ip_present_in_arp_cache(&dst_ip) == false) {
158//        NETD_DEBUG("refresh_arp_cache: event dispatched\n");
159        r = event_dispatch(ws);
160        if (err_is_fail(r)) {
161            DEBUG_ERR(r, "in event_dispatch");
162            abort();
163        }
164   } // end while: till arp not present
165   return find_ip_arp_cache(&dst_ip);
166}
167
168static errval_t ARP_resolve_request(struct net_ARP_binding *cc,
169            ipv4addr_t ip, uint32_t iface, bool force,
170            errval_t *err, uint64_t *mac)
171{
172    NETD_DEBUG("ARP_resolve_request: client asking ARP lookup for ip %"
173            PRIu32" over iface %"PRIu32"\n", ip, iface);
174
175    *mac = refresh_cache(ip);
176    assert(*mac != 0);
177//    assert(!"NYI ARP resolve request");
178    NETD_DEBUG("ARP_resolve_request: MAC found for ARP request ip %"
179            PRIu32" over iface %"PRIu32" == %"PRIx64"\n",
180            ip, iface, *mac);
181    *err = SYS_ERR_OK;
182    return SYS_ERR_OK;
183} // end function: ARP_resolve_request
184
185
186// Initialzes the ARP lookup service
187int init_ARP_lookup_service(struct netd_state *state, char *dev_name)
188{
189    errval_t err = SYS_ERR_OK; // default return value
190
191    // sanity check on parameter
192    assert(dev_name != NULL);
193
194    // start the port management service
195    snprintf(state->ARP_service_name, sizeof(state->ARP_service_name), "%s%s", dev_name,
196             NET_ARP_LOOKUP_SUFFIX);
197    state->ARP_service_exported = false;
198    state->registered_user_list = NULL;
199
200    NETD_DEBUG("init_ARP_lookup_service called [%s]\n", state->ARP_service_name);
201
202   // exporting net_ports interface
203    err = net_ARP_export(state, export_ARP_cb, connect_ARP_cb,
204            get_default_waitset(), IDC_EXPORT_FLAGS_DEFAULT);
205
206    if (err_is_fail(err)) {
207        USER_PANIC("net_ARP_export failed!");
208        return err;
209    }
210
211    // wait till ports export is actually done
212    struct waitset *ws = get_default_waitset();
213
214
215    while (!state->ARP_service_exported) {
216        err = event_dispatch(ws);
217        if (err_is_fail(err)) {
218            DEBUG_ERR(err, "in event_dispatch for init_ARP_service");
219            return err;
220        }
221    } // end while:
222
223    return err;
224} // end function: init_ARP_service
225