Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/inetsrv/inetping.c

    r9749e47 ra1a101d  
    11/*
    2  * Copyright (c) 2013 Jiri Svoboda
    3  * Copyright (c) 2013 Martin Decky
     2 * Copyright (c) 2012 Jiri Svoboda
    43 * All rights reserved.
    54 *
     
    4443#include <stdlib.h>
    4544#include <sys/types.h>
    46 #include <types/inetping.h>
     45
    4746#include "icmp.h"
    48 #include "icmpv6.h"
    4947#include "icmp_std.h"
    5048#include "inetsrv.h"
     
    5755static uint16_t inetping_ident = 0;
    5856
     57static inetping_client_t *inetping_client_find(uint16_t);
     58
    5959static int inetping_send(inetping_client_t *client, inetping_sdu_t *sdu)
    6060{
    61         if (sdu->src.version != sdu->dest.version)
    62                 return EINVAL;
    63 
    64         switch (sdu->src.version) {
    65         case ip_v4:
    66                 return icmp_ping_send(client->ident, sdu);
    67         case ip_v6:
    68                 return icmpv6_ping_send(client->ident, sdu);
    69         default:
    70                 return EINVAL;
    71         }
    72 }
    73 
    74 static int inetping_get_srcaddr(inetping_client_t *client,
    75     inet_addr_t *remote, inet_addr_t *local)
     61        return icmp_ping_send(client->ident, sdu);
     62}
     63
     64static int inetping_get_srcaddr(inetping_client_t *client, inet_addr_t *remote,
     65    inet_addr_t *local)
    7666{
    7767        return inet_get_srcaddr(remote, ICMP_TOS, local);
    7868}
    7969
     70int inetping_recv(uint16_t ident, inetping_sdu_t *sdu)
     71{
     72        inetping_client_t *client;
     73        async_exch_t *exch;
     74        ipc_call_t answer;
     75
     76        client = inetping_client_find(ident);
     77        if (client == NULL) {
     78                log_msg(LOG_DEFAULT, LVL_DEBUG, "Unknown ICMP ident. Dropping.");
     79                return ENOENT;
     80        }
     81
     82        exch = async_exchange_begin(client->sess);
     83
     84        aid_t req = async_send_3(exch, INETPING_EV_RECV, sdu->src.ipv4,
     85            sdu->dest.ipv4, sdu->seq_no, &answer);
     86        int rc = async_data_write_start(exch, sdu->data, sdu->size);
     87        async_exchange_end(exch);
     88
     89        if (rc != EOK) {
     90                async_forget(req);
     91                return rc;
     92        }
     93
     94        sysarg_t retval;
     95        async_wait_for(req, &retval);
     96        if (retval != EOK) {
     97                return retval;
     98        }
     99
     100        return EOK;
     101}
     102
     103static void inetping_send_srv(inetping_client_t *client, ipc_callid_t callid,
     104    ipc_call_t *call)
     105{
     106        inetping_sdu_t sdu;
     107        int rc;
     108
     109        log_msg(LOG_DEFAULT, LVL_DEBUG, "inetping_send_srv()");
     110
     111        rc = async_data_write_accept((void **) &sdu.data, false, 0, 0, 0,
     112            &sdu.size);
     113        if (rc != EOK) {
     114                async_answer_0(callid, rc);
     115                return;
     116        }
     117
     118        sdu.src.ipv4 = IPC_GET_ARG1(*call);
     119        sdu.dest.ipv4 = IPC_GET_ARG2(*call);
     120        sdu.seq_no = IPC_GET_ARG3(*call);
     121
     122        rc = inetping_send(client, &sdu);
     123        free(sdu.data);
     124
     125        async_answer_0(callid, rc);
     126}
     127
     128static void inetping_get_srcaddr_srv(inetping_client_t *client,
     129    ipc_callid_t callid, ipc_call_t *call)
     130{
     131        inet_addr_t remote;
     132        inet_addr_t local;
     133        int rc;
     134
     135        log_msg(LOG_DEFAULT, LVL_DEBUG, "inetping_get_srcaddr_srv()");
     136
     137        remote.ipv4 = IPC_GET_ARG1(*call);
     138        local.ipv4 = 0;
     139
     140        rc = inetping_get_srcaddr(client, &remote, &local);
     141        async_answer_1(callid, rc, local.ipv4);
     142}
     143
     144static int inetping_client_init(inetping_client_t *client)
     145{
     146        async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
     147        if (sess == NULL)
     148                return ENOMEM;
     149
     150        client->sess = sess;
     151        link_initialize(&client->client_list);
     152
     153        fibril_mutex_lock(&client_list_lock);
     154        client->ident = ++inetping_ident;
     155        list_append(&client->client_list, &client_list);
     156        fibril_mutex_unlock(&client_list_lock);
     157
     158        return EOK;
     159}
     160
     161static void inetping_client_fini(inetping_client_t *client)
     162{
     163        async_hangup(client->sess);
     164        client->sess = NULL;
     165
     166        fibril_mutex_lock(&client_list_lock);
     167        list_remove(&client->client_list);
     168        fibril_mutex_unlock(&client_list_lock);
     169}
     170
    80171static inetping_client_t *inetping_client_find(uint16_t ident)
    81172{
    82173        fibril_mutex_lock(&client_list_lock);
    83174
    84         list_foreach(client_list, client_list, inetping_client_t, client) {
     175        list_foreach(client_list, link) {
     176                inetping_client_t *client = list_get_instance(link,
     177                    inetping_client_t, client_list);
     178
    85179                if (client->ident == ident) {
    86180                        fibril_mutex_unlock(&client_list_lock);
     
    93187}
    94188
    95 int inetping_recv(uint16_t ident, inetping_sdu_t *sdu)
    96 {
    97         inetping_client_t *client = inetping_client_find(ident);
    98         if (client == NULL) {
    99                 log_msg(LOG_DEFAULT, LVL_DEBUG, "Unknown ICMP ident. Dropping.");
    100                 return ENOENT;
    101         }
    102 
    103         async_exch_t *exch = async_exchange_begin(client->sess);
    104 
    105         ipc_call_t answer;
    106         aid_t req = async_send_1(exch, INETPING_EV_RECV, sdu->seq_no, &answer);
    107 
    108         int rc = async_data_write_start(exch, &sdu->src, sizeof(sdu->src));
    109         if (rc != EOK) {
    110                 async_exchange_end(exch);
    111                 async_forget(req);
    112                 return rc;
    113         }
    114 
    115         rc = async_data_write_start(exch, &sdu->dest, sizeof(sdu->dest));
    116         if (rc != EOK) {
    117                 async_exchange_end(exch);
    118                 async_forget(req);
    119                 return rc;
    120         }
    121 
    122         rc = async_data_write_start(exch, sdu->data, sdu->size);
    123 
    124         async_exchange_end(exch);
    125 
    126         if (rc != EOK) {
    127                 async_forget(req);
    128                 return rc;
    129         }
    130 
    131         sysarg_t retval;
    132         async_wait_for(req, &retval);
    133 
    134         return (int) retval;
    135 }
    136 
    137 static void inetping_send_srv(inetping_client_t *client, ipc_callid_t iid,
    138     ipc_call_t *icall)
    139 {
    140         log_msg(LOG_DEFAULT, LVL_DEBUG, "inetping_send_srv()");
    141 
    142         inetping_sdu_t sdu;
     189void inetping_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
     190{
     191        inetping_client_t client;
    143192        int rc;
    144193
    145         sdu.seq_no = IPC_GET_ARG1(*icall);
    146 
    147         ipc_callid_t callid;
    148         size_t size;
    149         if (!async_data_write_receive(&callid, &size)) {
    150                 async_answer_0(callid, EREFUSED);
    151                 async_answer_0(iid, EREFUSED);
    152                 return;
    153         }
    154 
    155         if (size != sizeof(sdu.src)) {
    156                 async_answer_0(callid, EINVAL);
    157                 async_answer_0(iid, EINVAL);
    158                 return;
    159         }
    160 
    161         rc = async_data_write_finalize(callid, &sdu.src, size);
    162         if (rc != EOK) {
    163                 async_answer_0(callid, rc);
    164                 async_answer_0(iid, rc);
    165                 return;
    166         }
    167 
    168         if (!async_data_write_receive(&callid, &size)) {
    169                 async_answer_0(callid, EREFUSED);
    170                 async_answer_0(iid, EREFUSED);
    171                 return;
    172         }
    173 
    174         if (size != sizeof(sdu.dest)) {
    175                 async_answer_0(callid, EINVAL);
    176                 async_answer_0(iid, EINVAL);
    177                 return;
    178         }
    179 
    180         rc = async_data_write_finalize(callid, &sdu.dest, size);
    181         if (rc != EOK) {
    182                 async_answer_0(callid, rc);
    183                 async_answer_0(iid, rc);
    184                 return;
    185         }
    186 
    187         rc = async_data_write_accept((void **) &sdu.data, false, 0, 0, 0,
    188             &sdu.size);
    189         if (rc != EOK) {
    190                 async_answer_0(iid, rc);
    191                 return;
    192         }
    193 
    194         rc = inetping_send(client, &sdu);
    195         free(sdu.data);
    196 
    197         async_answer_0(iid, rc);
    198 }
    199 
    200 static void inetping_get_srcaddr_srv(inetping_client_t *client,
    201     ipc_callid_t iid, ipc_call_t *icall)
    202 {
    203         log_msg(LOG_DEFAULT, LVL_DEBUG, "inetping_get_srcaddr_srv()");
    204 
    205         ipc_callid_t callid;
    206         size_t size;
    207 
    208         inet_addr_t local;
    209         inet_addr_t remote;
    210 
    211         if (!async_data_write_receive(&callid, &size)) {
    212                 async_answer_0(callid, EREFUSED);
    213                 async_answer_0(iid, EREFUSED);
    214                 return;
    215         }
    216 
    217         if (size != sizeof(remote)) {
    218                 async_answer_0(callid, EINVAL);
    219                 async_answer_0(iid, EINVAL);
    220                 return;
    221         }
    222 
    223         int rc = async_data_write_finalize(callid, &remote, size);
    224         if (rc != EOK) {
    225                 async_answer_0(callid, rc);
    226                 async_answer_0(iid, rc);
    227                 return;
    228         }
    229 
    230         rc = inetping_get_srcaddr(client, &remote, &local);
    231         if (rc != EOK) {
    232                 async_answer_0(iid, rc);
    233                 return;
    234         }
    235 
    236         if (!async_data_read_receive(&callid, &size)) {
    237                 async_answer_0(callid, EREFUSED);
    238                 async_answer_0(iid, EREFUSED);
    239                 return;
    240         }
    241 
    242         if (size != sizeof(local)) {
    243                 async_answer_0(callid, EINVAL);
    244                 async_answer_0(iid, EINVAL);
    245                 return;
    246         }
    247 
    248         rc = async_data_read_finalize(callid, &local, size);
    249         if (rc != EOK)
    250                 async_answer_0(callid, rc);
    251 
    252         async_answer_0(iid, rc);
    253 }
    254 
    255 static int inetping_client_init(inetping_client_t *client)
    256 {
    257         async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
    258         if (sess == NULL)
    259                 return ENOMEM;
    260 
    261         client->sess = sess;
    262         link_initialize(&client->client_list);
    263 
    264         fibril_mutex_lock(&client_list_lock);
    265         client->ident = ++inetping_ident;
    266         list_append(&client->client_list, &client_list);
    267         fibril_mutex_unlock(&client_list_lock);
    268 
    269         return EOK;
    270 }
    271 
    272 static void inetping_client_fini(inetping_client_t *client)
    273 {
    274         async_hangup(client->sess);
    275         client->sess = NULL;
    276 
    277         fibril_mutex_lock(&client_list_lock);
    278         list_remove(&client->client_list);
    279         fibril_mutex_unlock(&client_list_lock);
    280 }
    281 
    282 void inetping_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
    283 {
    284194        log_msg(LOG_DEFAULT, LVL_DEBUG, "inetping_conn()");
    285195
     
    287197        async_answer_0(iid, EOK);
    288198
    289         inetping_client_t client;
    290         int rc = inetping_client_init(&client);
     199        rc = inetping_client_init(&client);
    291200        if (rc != EOK)
    292201                return;
Note: See TracChangeset for help on using the changeset viewer.