Ignore:
File:
1 edited

Legend:

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

    rb417559 r3e6a98c5  
    4343#include <stdlib.h>
    4444#include <str.h>
    45 #include <net/socket_codes.h>
     45
    4646#include "addrobj.h"
    4747#include "inetsrv.h"
     
    4949#include "pdu.h"
    5050
    51 static bool first_link = true;
    52 static bool first_link6 = true;
    53 
    54 static FIBRIL_MUTEX_INITIALIZE(ip_ident_lock);
    55 static uint16_t ip_ident = 0;
    56 
    57 static int inet_iplink_recv(iplink_t *, iplink_recv_sdu_t *, uint16_t);
    58 static inet_link_t *inet_link_get_by_id_locked(sysarg_t);
     51static int inet_link_open(service_id_t sid);
     52static int inet_iplink_recv(iplink_t *ilink, iplink_sdu_t *sdu);
    5953
    6054static iplink_ev_ops_t inet_iplink_ev_ops = {
     
    6256};
    6357
    64 static LIST_INITIALIZE(inet_links);
    65 static FIBRIL_MUTEX_INITIALIZE(inet_links_lock);
    66 
    67 static addr128_t link_local_node_ip =
    68     {0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xfe, 0, 0, 0};
    69 
    70 static void inet_link_local_node_ip(addr48_t mac_addr,
    71     addr128_t ip_addr)
    72 {
    73         memcpy(ip_addr, link_local_node_ip, 16);
    74        
    75         ip_addr[8] = mac_addr[0] ^ 0x02;
    76         ip_addr[9] = mac_addr[1];
    77         ip_addr[10] = mac_addr[2];
    78         ip_addr[13] = mac_addr[3];
    79         ip_addr[14] = mac_addr[4];
    80         ip_addr[15] = mac_addr[5];
    81 }
    82 
    83 static int inet_iplink_recv(iplink_t *iplink, iplink_recv_sdu_t *sdu, uint16_t af)
    84 {
     58static LIST_INITIALIZE(inet_link_list);
     59static FIBRIL_MUTEX_INITIALIZE(inet_discovery_lock);
     60
     61static int inet_iplink_recv(iplink_t *iplink, iplink_sdu_t *sdu)
     62{
     63        inet_packet_t packet;
     64        int rc;
     65
    8566        log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_iplink_recv()");
    86        
    87         int rc;
    88         inet_packet_t packet;
    89        
    90         switch (af) {
    91         case AF_INET:
    92                 rc = inet_pdu_decode(sdu->data, sdu->size, &packet);
    93                 break;
    94         case AF_INET6:
    95                 rc = inet_pdu_decode6(sdu->data, sdu->size, &packet);
    96                 break;
    97         default:
    98                 log_msg(LOG_DEFAULT, LVL_DEBUG, "invalid address family");
    99                 return EINVAL;
    100         }
    101        
     67        rc = inet_pdu_decode(sdu->data, sdu->size, &packet);
    10268        if (rc != EOK) {
    10369                log_msg(LOG_DEFAULT, LVL_DEBUG, "failed decoding PDU");
    10470                return rc;
    10571        }
    106        
     72
    10773        log_msg(LOG_DEFAULT, LVL_DEBUG, "call inet_recv_packet()");
    10874        rc = inet_recv_packet(&packet);
    10975        log_msg(LOG_DEFAULT, LVL_DEBUG, "call inet_recv_packet -> %d", rc);
    11076        free(packet.data);
    111        
     77
    11278        return rc;
     79}
     80
     81static int inet_link_check_new(void)
     82{
     83        bool already_known;
     84        category_id_t iplink_cat;
     85        service_id_t *svcs;
     86        size_t count, i;
     87        int rc;
     88
     89        fibril_mutex_lock(&inet_discovery_lock);
     90
     91        rc = loc_category_get_id("iplink", &iplink_cat, IPC_FLAG_BLOCKING);
     92        if (rc != EOK) {
     93                log_msg(LOG_DEFAULT, LVL_ERROR, "Failed resolving category 'iplink'.");
     94                fibril_mutex_unlock(&inet_discovery_lock);
     95                return ENOENT;
     96        }
     97
     98        rc = loc_category_get_svcs(iplink_cat, &svcs, &count);
     99        if (rc != EOK) {
     100                log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting list of IP links.");
     101                fibril_mutex_unlock(&inet_discovery_lock);
     102                return EIO;
     103        }
     104
     105        for (i = 0; i < count; i++) {
     106                already_known = false;
     107
     108                list_foreach(inet_link_list, ilink_link) {
     109                        inet_link_t *ilink = list_get_instance(ilink_link,
     110                            inet_link_t, link_list);
     111                        if (ilink->svc_id == svcs[i]) {
     112                                already_known = true;
     113                                break;
     114                        }
     115                }
     116
     117                if (!already_known) {
     118                        log_msg(LOG_DEFAULT, LVL_DEBUG, "Found IP link '%lu'",
     119                            (unsigned long) svcs[i]);
     120                        rc = inet_link_open(svcs[i]);
     121                        if (rc != EOK)
     122                                log_msg(LOG_DEFAULT, LVL_ERROR, "Could not open IP link.");
     123                }
     124        }
     125
     126        fibril_mutex_unlock(&inet_discovery_lock);
     127        return EOK;
    113128}
    114129
     
    132147        if (ilink->svc_name != NULL)
    133148                free(ilink->svc_name);
    134        
    135149        free(ilink);
    136150}
    137151
    138 int inet_link_open(service_id_t sid)
     152static int inet_link_open(service_id_t sid)
    139153{
    140154        inet_link_t *ilink;
    141         inet_addr_t iaddr;
     155        iplink_addr_t iaddr;
    142156        int rc;
    143157
     
    175189                goto error;
    176190        }
    177        
    178         /*
    179          * Get the MAC address of the link. If the link has a MAC
    180          * address, we assume that it supports NDP.
    181          */
    182         rc = iplink_get_mac48(ilink->iplink, &ilink->mac);
    183         ilink->mac_valid = (rc == EOK);
    184191
    185192        log_msg(LOG_DEFAULT, LVL_DEBUG, "Opened IP link '%s'", ilink->svc_name);
    186 
    187         fibril_mutex_lock(&inet_links_lock);
    188 
    189         if (inet_link_get_by_id_locked(sid) != NULL) {
    190                 fibril_mutex_unlock(&inet_links_lock);
    191                 log_msg(LOG_DEFAULT, LVL_DEBUG, "Link %zu already open",
    192                     sid);
    193                 rc = EEXIST;
    194                 goto error;
    195         }
    196 
    197         list_append(&ilink->link_list, &inet_links);
    198         fibril_mutex_unlock(&inet_links_lock);
    199 
    200         inet_addrobj_t *addr = NULL;
    201        
    202         /* XXX FIXME Cannot rely on loopback being the first IP link service!! */
    203         if (first_link) {
    204                 addr = inet_addrobj_new();
    205                
    206                 inet_naddr(&addr->naddr, 127, 0, 0, 1, 24);
    207                 first_link = false;
    208         }
    209        
    210         if (addr != NULL) {
    211                 addr->ilink = ilink;
    212                 addr->name = str_dup("v4a");
    213                
    214                 rc = inet_addrobj_add(addr);
    215                 if (rc == EOK) {
    216                         inet_naddr_addr(&addr->naddr, &iaddr);
    217                         rc = iplink_addr_add(ilink->iplink, &iaddr);
    218                         if (rc != EOK) {
    219                                 log_msg(LOG_DEFAULT, LVL_ERROR,
    220                                     "Failed setting IPv4 address on internet link.");
    221                                 inet_addrobj_remove(addr);
    222                                 inet_addrobj_delete(addr);
    223                         }
    224                 } else {
    225                         log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding IPv4 address.");
    226                         inet_addrobj_delete(addr);
    227                 }
    228         }
    229        
    230         inet_addrobj_t *addr6 = NULL;
    231        
    232         if (first_link6) {
    233                 addr6 = inet_addrobj_new();
    234                
    235                 inet_naddr6(&addr6->naddr, 0, 0, 0, 0, 0, 0, 0, 1, 128);
    236                 first_link6 = false;
    237         } else if (ilink->mac_valid) {
    238                 addr6 = inet_addrobj_new();
    239                
    240                 addr128_t link_local;
    241                 inet_link_local_node_ip(ilink->mac, link_local);
    242                
    243                 inet_naddr_set6(link_local, 64, &addr6->naddr);
    244         }
    245        
    246         if (addr6 != NULL) {
    247                 addr6->ilink = ilink;
    248                 addr6->name = str_dup("v6a");
    249                
    250                 rc = inet_addrobj_add(addr6);
    251                 if (rc == EOK) {
    252                         inet_naddr_addr(&addr6->naddr, &iaddr);
    253                         rc = iplink_addr_add(ilink->iplink, &iaddr);
    254                         if (rc != EOK) {
    255                                 log_msg(LOG_DEFAULT, LVL_ERROR,
    256                                     "Failed setting IPv6 address on internet link.");
    257                                 inet_addrobj_remove(addr6);
    258                                 inet_addrobj_delete(addr6);
    259                         }
    260                 } else {
    261                         log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding IPv6 address.");
    262                         inet_addrobj_delete(addr6);
    263                 }
    264         }
    265        
    266         log_msg(LOG_DEFAULT, LVL_DEBUG, "Configured link '%s'.", ilink->svc_name);
     193        list_append(&ilink->link_list, &inet_link_list);
     194
     195        inet_addrobj_t *addr;
     196
     197        static int first = 1;
     198        /* XXX For testing: set static IP address 192.168.0.4/24 */
     199        addr = inet_addrobj_new();
     200        if (first) {
     201                addr->naddr.ipv4 = (127 << 24) + (0 << 16) + (0 << 8) + 1;
     202                first = 0;
     203        } else {
     204                addr->naddr.ipv4 = (192 << 24) + (168 << 16) + (0 << 8) + 4;
     205        }
     206        addr->naddr.bits = 24;
     207        addr->ilink = ilink;
     208        addr->name = str_dup("v4a");
     209        rc = inet_addrobj_add(addr);
     210        if (rc != EOK) {
     211                log_msg(LOG_DEFAULT, LVL_ERROR, "Failed setting IP address on internet link.");
     212                inet_addrobj_delete(addr);
     213                /* XXX Roll back */
     214                return rc;
     215        }
     216
     217        iaddr.ipv4 = addr->naddr.ipv4;
     218        rc = iplink_addr_add(ilink->iplink, &iaddr);
     219        if (rc != EOK) {
     220                log_msg(LOG_DEFAULT, LVL_ERROR, "Failed setting IP address on internet link.");
     221                inet_addrobj_remove(addr);
     222                inet_addrobj_delete(addr);
     223                /* XXX Roll back */
     224                return rc;
     225        }
     226
    267227        return EOK;
    268        
     228
    269229error:
    270230        if (ilink->iplink != NULL)
    271231                iplink_close(ilink->iplink);
    272        
    273232        inet_link_delete(ilink);
    274233        return rc;
    275234}
    276235
    277 /** Send IPv4 datagram over Internet link
    278  *
    279  * @param ilink Internet link
    280  * @param lsrc  Source IPv4 address
    281  * @param ldest Destination IPv4 address
    282  * @param dgram IPv4 datagram body
    283  * @param proto Protocol
    284  * @param ttl   Time-to-live
    285  * @param df    Do-not-Fragment flag
    286  *
    287  * @return EOK on success
    288  * @return ENOMEM when not enough memory to create the datagram
    289  * @return ENOTSUP if networking mode is not supported
    290  *
    291  */
    292 int inet_link_send_dgram(inet_link_t *ilink, addr32_t lsrc, addr32_t ldest,
    293     inet_dgram_t *dgram, uint8_t proto, uint8_t ttl, int df)
    294 {
    295         addr32_t src_v4;
    296         uint16_t src_af = inet_addr_get(&dgram->src, &src_v4, NULL);
    297         if (src_af != AF_INET)
    298                 return EINVAL;
    299        
    300         addr32_t dest_v4;
    301         uint16_t dest_af = inet_addr_get(&dgram->dest, &dest_v4, NULL);
    302         if (dest_af != AF_INET)
    303                 return EINVAL;
    304        
     236static void inet_link_cat_change_cb(void)
     237{
     238        (void) inet_link_check_new();
     239}
     240
     241int inet_link_discovery_start(void)
     242{
     243        int rc;
     244
     245        rc = loc_register_cat_change_cb(inet_link_cat_change_cb);
     246        if (rc != EOK) {
     247                log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering callback for IP link "
     248                    "discovery (%d).", rc);
     249                return rc;
     250        }
     251
     252        return inet_link_check_new();
     253}
     254
     255/** Send datagram over Internet link */
     256int inet_link_send_dgram(inet_link_t *ilink, inet_addr_t *lsrc,
     257    inet_addr_t *ldest, inet_dgram_t *dgram, uint8_t proto, uint8_t ttl, int df)
     258{
     259        iplink_sdu_t sdu;
     260        inet_packet_t packet;
     261        int rc;
     262        size_t offs, roffs;
     263
    305264        /*
    306265         * Fill packet structure. Fragmentation is performed by
    307266         * inet_pdu_encode().
    308267         */
    309        
    310         iplink_sdu_t sdu;
    311        
    312         sdu.src = lsrc;
    313         sdu.dest = ldest;
    314        
    315         inet_packet_t packet;
    316        
    317268        packet.src = dgram->src;
    318269        packet.dest = dgram->dest;
     
    320271        packet.proto = proto;
    321272        packet.ttl = ttl;
    322        
    323         /* Allocate identifier */
    324         fibril_mutex_lock(&ip_ident_lock);
    325         packet.ident = ++ip_ident;
    326         fibril_mutex_unlock(&ip_ident_lock);
    327        
    328273        packet.df = df;
    329274        packet.data = dgram->data;
    330275        packet.size = dgram->size;
    331        
    332         int rc;
    333         size_t offs = 0;
    334        
     276
     277        sdu.lsrc.ipv4 = lsrc->ipv4;
     278        sdu.ldest.ipv4 = ldest->ipv4;
     279
     280        offs = 0;
    335281        do {
    336282                /* Encode one fragment */
    337                
    338                 size_t roffs;
    339                 rc = inet_pdu_encode(&packet, src_v4, dest_v4, offs, ilink->def_mtu,
    340                     &sdu.data, &sdu.size, &roffs);
     283                rc = inet_pdu_encode(&packet, offs, ilink->def_mtu, &sdu.data,
     284                    &sdu.size, &roffs);
    341285                if (rc != EOK)
    342286                        return rc;
    343                
     287
    344288                /* Send the PDU */
    345289                rc = iplink_send(ilink->iplink, &sdu);
    346                
    347290                free(sdu.data);
     291
    348292                offs = roffs;
    349293        } while (offs < packet.size);
    350        
     294
    351295        return rc;
    352296}
    353297
    354 /** Send IPv6 datagram over Internet link
    355  *
    356  * @param ilink Internet link
    357  * @param ldest Destination MAC address
    358  * @param dgram IPv6 datagram body
    359  * @param proto Next header
    360  * @param ttl   Hop limit
    361  * @param df    Do-not-Fragment flag (unused)
    362  *
    363  * @return EOK on success
    364  * @return ENOMEM when not enough memory to create the datagram
    365  *
    366  */
    367 int inet_link_send_dgram6(inet_link_t *ilink, addr48_t ldest,
    368     inet_dgram_t *dgram, uint8_t proto, uint8_t ttl, int df)
    369 {
    370         addr128_t src_v6;
    371         uint16_t src_af = inet_addr_get(&dgram->src, NULL, &src_v6);
    372         if (src_af != AF_INET6)
    373                 return EINVAL;
    374        
    375         addr128_t dest_v6;
    376         uint16_t dest_af = inet_addr_get(&dgram->dest, NULL, &dest_v6);
    377         if (dest_af != AF_INET6)
    378                 return EINVAL;
    379        
    380         iplink_sdu6_t sdu6;
    381         addr48(ldest, sdu6.dest);
    382        
    383         /*
    384          * Fill packet structure. Fragmentation is performed by
    385          * inet_pdu_encode6().
    386          */
    387        
    388         inet_packet_t packet;
    389        
    390         packet.src = dgram->src;
    391         packet.dest = dgram->dest;
    392         packet.tos = dgram->tos;
    393         packet.proto = proto;
    394         packet.ttl = ttl;
    395        
    396         /* Allocate identifier */
    397         fibril_mutex_lock(&ip_ident_lock);
    398         packet.ident = ++ip_ident;
    399         fibril_mutex_unlock(&ip_ident_lock);
    400        
    401         packet.df = df;
    402         packet.data = dgram->data;
    403         packet.size = dgram->size;
    404        
    405         int rc;
    406         size_t offs = 0;
    407        
    408         do {
    409                 /* Encode one fragment */
    410                
    411                 size_t roffs;
    412                 rc = inet_pdu_encode6(&packet, src_v6, dest_v6, offs, ilink->def_mtu,
    413                     &sdu6.data, &sdu6.size, &roffs);
    414                 if (rc != EOK)
    415                         return rc;
    416                
    417                 /* Send the PDU */
    418                 rc = iplink_send6(ilink->iplink, &sdu6);
    419                
    420                 free(sdu6.data);
    421                 offs = roffs;
    422         } while (offs < packet.size);
    423        
    424         return rc;
    425 }
    426 
    427 static inet_link_t *inet_link_get_by_id_locked(sysarg_t link_id)
    428 {
    429         assert(fibril_mutex_is_locked(&inet_links_lock));
    430 
    431         list_foreach(inet_links, link_list, inet_link_t, ilink) {
    432                 if (ilink->svc_id == link_id)
     298inet_link_t *inet_link_get_by_id(sysarg_t link_id)
     299{
     300        fibril_mutex_lock(&inet_discovery_lock);
     301
     302        list_foreach(inet_link_list, elem) {
     303                inet_link_t *ilink = list_get_instance(elem, inet_link_t,
     304                    link_list);
     305
     306                if (ilink->svc_id == link_id) {
     307                        fibril_mutex_unlock(&inet_discovery_lock);
    433308                        return ilink;
    434         }
    435 
     309                }
     310        }
     311
     312        fibril_mutex_unlock(&inet_discovery_lock);
    436313        return NULL;
    437 }
    438 
    439 inet_link_t *inet_link_get_by_id(sysarg_t link_id)
    440 {
    441         inet_link_t *ilink;
    442 
    443         fibril_mutex_lock(&inet_links_lock);
    444         ilink = inet_link_get_by_id_locked(link_id);
    445         fibril_mutex_unlock(&inet_links_lock);
    446 
    447         return ilink;
    448 }
    449 
    450 /** Get IDs of all links. */
    451 int inet_link_get_id_list(sysarg_t **rid_list, size_t *rcount)
    452 {
    453         sysarg_t *id_list;
    454         size_t count, i;
    455 
    456         fibril_mutex_lock(&inet_links_lock);
    457         count = list_count(&inet_links);
    458 
    459         id_list = calloc(count, sizeof(sysarg_t));
    460         if (id_list == NULL) {
    461                 fibril_mutex_unlock(&inet_links_lock);
    462                 return ENOMEM;
    463         }
    464 
    465         i = 0;
    466         list_foreach(inet_links, link_list, inet_link_t, ilink) {
    467                 id_list[i++] = ilink->svc_id;
    468                 log_msg(LOG_DEFAULT, LVL_NOTE, "add link to list");
    469         }
    470 
    471         fibril_mutex_unlock(&inet_links_lock);
    472 
    473         log_msg(LOG_DEFAULT, LVL_NOTE, "return %zu links", count);
    474         *rid_list = id_list;
    475         *rcount = count;
    476 
    477         return EOK;
    478314}
    479315
Note: See TracChangeset for help on using the changeset viewer.